需求是酱紫:app和web都要展示图片,后台的管理员是找广告公司给ps的图片,每张都是1M大小,后台数据库里存的是相对路径。app可以自行在前端压缩一下,但是web就很头疼,一个页面几十m。所以希望能获取指定大小的裁剪过后的图片。
思路1: 后台每次上传图片,都用代码裁剪压缩成不同尺寸存起来。文件名后做个标记,多大多小。这个做法先排除了,太麻烦。
思路2:写一个http请求,调这个方法,传图片路径参数和要获取的大小,后台实时处理后返回。这个小项目还可以,图片一多,性能是个问题。
思路3:nginx来实现。
因为我们没c程序猿,也没有运维,nginx的image_filter也不会用,尝试网上找点开源的。找到了两个
一个是ngx_image_thumb ,中国人写的。用了一下感觉不错,比image_filter好用一点,因为裁剪方式有四种,也不用配置。关键是参数是跟在地址屁股后面的,对我们以前的代码没有任何影响。不过貌似这个有点小bug,image on;image_output on;这两个都打开才能生效。
另外一个是https://github.com/cubicdaiya/ngx_small_light 。 这个也很强大。优点是支持get传参来控制图片大小。例如http://127.0.0.1/a.jpg?dw=200&dh=200 。第二个优点是,可以预先设定图片的规格。比如我设置两种尺寸
small_light_pattern_define msize dw=500,dh=500,da=l,q=95,e=imagemagick,jpeghint=y;
small_light_pattern_define ssize dw=120,dh=120,da=l,q=95,e=imlib2,jpeghint=y;
# http://localhost:8000/small_light(p=msize)/img/filename.jpg -> generate msize image
# http://localhost:8000/small_light(p=ssize)/img/filename.jpg -> generate ssize image
然后可以把dw,dh这些都请求都直接过滤掉。这样的话,前端的人就只能访问到msize和ssize两种规格的图片。而不会随意的构造参数,让服务器白白生成各种规格的图片,有可能被人拿来搞破坏。我观察了一下twitter,图片就只有:large 和 :small两种。
不过上面两种方案都没有提供生成图片后,缓存起来,以免下次访问又重新裁剪一遍图片的功能。好在nginx有缓存模块可以使用,利用缓存就可以。下面是用ngx_image_thumb的配置。
http {
proxy_cache_path /var/cache/nginx/proxy_cache levels=1:2 keys_zone=images:500m inactive=24h max_size=1G;
server {
listen 80;
server_name 10.58.175.186;
location /static/ {
proxy_cache images;
proxy_cache_valid 200 1h;
proxy_cache_key "$scheme://$host$request_uri$is_args$args";
proxy_pass http://127.0.0.1:80/realstatic/;
}
location /realstatic/ {
alias /apache/cms/uploads/;
image on;
image_output on;
}
}
}
首先,设置一个cache,名字叫images大小500m,路径在/var/cache/nginx/proxy_cache
假设在/apache/cms/uploads/目录下有一个a.jpg,那么访问
http://10.58.175.186/static/a.jpg,请求被转发给/realstitic,然后把返回的图片缓存起来。
http://10.58.175.186/static/a.jpg!c200x200.jpg,则是200x200的图片
观察一下,/var/cache/nginx/proxy_cache,里面有两级目录,目录中缓存的就是图片,当然文件头部放了请求相关的信息,删掉之后发现就是图片。