無圖,純乾貨,信息量較大,慎入!javascript
最近幾天的成果,濃縮下來就是這麼一行代碼:html
document.getElementById('img1').src = 'http://www.mysite.com/imgproxy' + imgproxy(document.getElementById("img1").getAttribute('data-src'), 135, 85);
最初的時候只是看個人我的博客圖片大小高低不一,比較難看,試圖找一種方法可以統一各圖片的高度。在網上搜索的結果是,發現了幾個Jykell
的插件,例如jekyll-picture-tag,經過這個過程學到了很多東西,好比img標籤除了有srcset之外,還有一個額外的Picture標籤等等。原本想用這個插件,但另一個插件jekyll-cloudinary的做者說Picture標籤並很差,應該直接使用Cloudinary的服務。java
由此而想起在我上一篇文章中提到過的一篇教程中談到過的用國內的七牛雲作圖牀,因而開始嘗試把我網站文章中用到的圖片往七牛雲搬家,圖片搬家不是問題,但又想在博客網站上增長https服務,因而在問過個人朋友馬壯以後,在Cloudflare上開通了https服務,但這又形成另一個問題:七牛雲上雖然放了個人圖片,可是七牛雲自己不支持https服務,因而又得想辦法把圖片搬到Cloudinary。node
至此我我的的博客算是能夠告一段落。平心而論,七牛雲
的預置功能仍是很不錯的,至少它對於URL
的處理方式比Cloudinary
要簡單,但惟一的遺憾是它不支持https
。而若是圖片不支持https
而網站使用https
的話,Chrome
會在Console
裏報警告錯誤,而我對網站的要求是:一個警告都不能有。linux
在此過程當中,我開始思考一個問題:既然Cloudinary
和七牛雲
都提供基於URL
地址的圖片變換,那麼它們是怎麼作到的呢?根據我對PHP
的粗淺瞭解,最笨的方法能夠直接以PHP
讀文件的方式從硬盤先讀取圖片的源文件,而後經轉換後再以流的方式輸出給頁面,但這樣效率確定極低。因而通過搜索後發現了不少人推薦的libvips庫,再進一步搜索,在Github
上發現了有不少顆星的imgproxy這個庫,彷佛這就是我想要的東西。git
因而我開始嘗試動手往公司的服務器上部署imgproxy
。但這時候遇到一個問題,在CentOS
上,imgproxy
並無yum
安裝包,還須要先手工安裝libvips
,而後再編譯,而最要命的是,公司的服務器在國內,沒法經過wget
的方式直接安裝國外的軟件包,由此而我須要先把安裝包下載到本地,而後再上傳到公司的服務器上。這時候我又想取個巧,使用iterm內置的scp用鼠標拖拽的方式上傳文件。按照操做步驟的說明,安裝好了以後卻發現iterm
的scp
按鈕依然是灰色的,這時才發現是因爲服務器上的fish
版本太低,只有1.3
,而最新的已是2.6
了。因而安裝2.6的repo,嘗試更新fish
,卻老是報衝突。由此而想到將fish 1.3
先卸載,就在這時災難發生了。github
我直接執行了yum remove fish
,可是在作這一步以前,我沒有將root
用戶的shell
切換回bash
,由此而致使了root
用戶找不到它的shell
,由於它還在試圖尋找fish
。這是一個致命的錯誤,我記得本身當時隱隱約約有預感,但仍是沒有特別在乎,以爲也許Linux
系統會自動爲root
用戶賦予一個缺省的shell
。結果我高估了Linux
系統的能力。docker
退出登陸以後,我發現root
用戶登陸不上了!若是不仔細觀察的話,你會感受它的不能登陸的症狀和密碼錯誤很是相似,但實際表現其實略有不一樣,在SSH
端是不大看得出來的。個人第一反應是,若是root
用戶沒法經過SSH
登陸了,那麼應該經過console
端登陸。shell
但當天下午,使人驚訝的是連console
端也登不上了!這時候我意識到問題嚴重了。在網上搜索的結果是有人說應該以runlevel 1的方式登陸,而後嘗試修復/etc/shadow
。但我徹底不瞭解對於一臺雲主機應該如何進入runlevel 1
。只好提工單給客服。而客服的技術水平你們應該是知道的,只是建議我重置密碼以後再嘗試一下。而重置密碼必需要關機再重啓,就這樣來回折騰了好久也修很差。npm
在通過了漫長的等待以後,終於驚動了一個技術人員。他指出若是我必需要進runlevel 1
的話,能夠在系統開機的前3秒之間按下鍵盤的e鍵,而後就能夠進入runlevel 1
了。
但問題是這是一臺雲主機,如何能在開機前3秒按鍵呢?好在如今雲主機的console
功能很是發達,你能夠開着console
重啓,這時候網絡斷掉,而後不停地刷新console
,你會在電腦開機的一瞬間看到一個有字的黑畫面,這時候迅速按下e
鍵也能進入系統。而後再次按下e
,把啓動模式修改成Linux single
。
按照他的指導,我終於可以以runlevel 1
的方式進入了系統,首先嚐試用/etc/passwd
重建/etc/shadow
,再次重啓,無果,仍是登陸不進去。至此爲止,全部關於密碼的努力均告失敗。我想,惟一的辦法只能嘗試看能不能切換root
用戶的shell
:
chsh -s /bin/bash
把root
用戶的shell
切換成bash
以後,再次重啓電腦,果真能夠成功登陸了!
接下來,我仍是須要安裝fish
,但yum install fish
結果fish
仍是1.3
。我還要繼續上次不成功的征程。再次把fish
從1.3
換成2.6
。依然衝突。此次我學精了,我先把root
的shell
腳本切換成bash
,而後yum remove fish
,再次安裝,發現這個fish 1.3
的來源是一個不知何時裝上的名叫dag
的repo
,因而嘗試把這個dag
的repo
禁止掉:
yum-config-manager --disable dag
而後再次安裝,終於裝上了fish 2.6
。
至此,基本全部阻塞性因素都消除了,我開始將libvips
的代碼拖拽進服務器,而後編譯。但這時候問題又來了,imgproxy
必須運行在docker
裏,而說明文檔上只說須要本身build
一個docker
,但並無指明以什麼操做系統爲基礎去build
,好在官方提供了一個它們本身的docker
文件,能夠直接運行imgproxy
。
啊!早知如此,我何須折騰這麼一大圈?還差點毀掉了個人系統。不過好在學到了很多東西。好吧,因而咱們開始直接安裝使用imgproxy
官方提供的docker
:
$ docker pull darthsim/imgproxy:latest $ docker run -e IMGPROXY_KEY=$YOUR_KEY -e IMGPROXY_SALT=$YOUR_SALT -p 8080:8080 -t darthsim/imgproxy
可是這個imgproxy
的使用方式又是很是的不友好,它徹底不像七牛雲
或者Cloudinary
那樣直接在URL
地址上構建就好了,它須要本身根據本身的key
和salt
產生簽名,而後再用簽名構建URL
,它給了各類語言的例子,惟獨沒有java
的,最後我只好根據它本身的javascript
語言的例子構建一個js
代碼,用於替換頁面中的圖片連接。
但問題又來了,它給定的這個包是一個node
的js
腳本,裏面有require
語句,沒法直接用於瀏覽器。這時候又得請出browerify
,用它來編譯node
的腳本爲能夠供瀏覽器直接使用的腳本。好在過程並不複雜,編譯以後獲得的bundle.js
文件,咱們直接在頁面中引用就好了。因而就獲得了本文開頭的一行代碼:
<!DOCTYPE html> <html> <head> </head> <body> <img id="img1" data-src="http://www.mysite.com/img/somepic.png" src="" /> <script src="bundle.js"></script> <script> window.onload = function() { document.getElementById('img1').src = 'http://www.mysite.com/imgproxy' + imgproxy(document.getElementById("img1").getAttribute('data-src'), 135, 85); } </script> </body> </html>
以及相關的js:
window.imgproxy = function (url, width, height) { const crypto = require('crypto') const KEY = 'somekey' const SALT = 'somesalt' const urlSafeBase64 = (string) => { return new Buffer(string).toString('base64').replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_') } const hexDecode = (hex) => Buffer.from(hex, 'hex') const sign = (salt, target, secret) => { const hmac = crypto.createHmac('sha256', hexDecode(secret)) hmac.update(hexDecode(salt)) hmac.update(target) return urlSafeBase64(hmac.digest()) } const resizing_type = 'fit' const gravity = 'no' const enlarge = 0 const extension = 'jpg' const encoded_url = urlSafeBase64(url) const path = `/${resizing_type}/${width}/${height}/${gravity}/${enlarge}/${encoded_url}.${extension}` const signature = sign(SALT, path, KEY) const result = `/${signature}${path}` return result; }
固然你須要npm install crypto
,而後編譯:
browserify main.js > bundle.js
你能夠把你本身獲得的URL
去和這個網站生成的URL
作對比,若是徹底一致,就說明你的代碼配置正確,不然就仍是有可能不成功。
這就是這兩天來的結果。我學到了很多東西,你學到了嗎?