无图,纯干货,信息量较大,慎入!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
作对比,若是彻底一致,就说明你的代码配置正确,不然就仍是有可能不成功。
这就是这两天来的结果。我学到了很多东西,你学到了吗?