你还在用 ImageMagick 生成网站的上传图片缩略图吗?其实有更好的方法一部到位,简单有效。php
现而今有很是多的云存储服务支持图片空间,并根据设定的规则来生成空间里面的图片缩略图了,例如 UpYun、Aliyun OSS 都支持。html
但有时候咱们会由于一些其余的考虑(例如:价格因素),选择本地文件存储上传文件,这个时候,咱们如何实现图片缩略图呢?nginx
其实 Nginx 内置了 ngx_http_image_filter_module 能够帮助你处理图片:git
咱们经常使用的可能就是缩放和裁剪了,根据业务和设计须要,在合适的位置不一样尺寸的缩略图。github
可能一些标准的 Nginx 安装包没有带这个 module 的,你须要使用 Nginx 官方的源安装,并额外安装 nginx-module-image-filter
这个包:ubuntu
curl -O http://nginx.org/keys/nginx_signing.key sudo apt-key add nginx_signing.key sudo bash -c 'echo "deb http://nginx.org/packages/ubuntu/ $(lsb_release -cs) nginx deb-src http://nginx.org/packages/ubuntu/ $(lsb_release -cs) nginx" > /etc/apt/sources.list.d/nginx-stable.list' sudo apt-get update sudo apt-get install -y nginx nginx-module-image-filter
也能够直接用作好的 安装脚本浏览器
curl -sSL https://git.io/vVHhf | bash
以 Ruby China 的场景为例,我设计了下面几种不一样的缩略图版本:缓存
版本名称 | 限定尺寸 (px) | 缩略方式 |
---|---|---|
large | 1920 | 限定宽度,高度自适应 |
lg | 192x192 | 固定宽度和高度 |
md | 96x96 | 固定宽度和高度 |
sm | 48x48 | 固定宽度和高度 |
xs | 32x32 | 固定宽度和高度 |
假定咱们的上传文件存放在 /var/www/homeland/public/uploads
里面。ruby
下面是 Ruby China 这个缩略图规则的完整 Nginx 配置:bash
/etc/nginx/nginx.conf
user nobody; worker_processes auto; pid /var/www/pids/nginx.pid; daemon on; # 载入 ngx_http_image_filter_module load_module modules/ngx_http_image_filter_module.so; http { # ... 省略 }
/etc/nginx/conf.d/ruby-china.conf
proxy_cache_path /var/www/cache/uploads-thumb levels=1:2 keys_zone=uploads_thumb:10m max_size=50G; server { listen 80 default_server; listen 443 ssl http2; root /var/www/homeland/public; location /uploads { expires 7d; gzip_static on; add_header Cache-Control public; add_header X-Pownered "nginx_image_filter"; # HTTP Response Header 增长 proxy_cache 的命中状态,以便于之后调试,检查问题 add_header X-Cache-Status $upstream_cache_status; proxy_pass http://127.0.0.1/_img/uploads; # 将缩略图缓存在服务,避免每次请求都从新生成 proxy_cache uploads_thumb; # 当收到 HTTP Header Pragma: no-cache 的时候,忽略 proxy_cache # 此配置能让浏览器强制刷新的时候,忽略 proxy_cache 从新生成缩略图 proxy_cache_bypass $http_pragma; # 因为 Upload 文件通常都没参数的,因此至今用 host + document_uri 做为 proxy_cache_key "$host$document_uri"; # 有效的文件,在服务器缓存 7 天 proxy_cache_valid 200 7d; proxy_cache_use_stale error timeout invalid_header updating; proxy_cache_revalidate on; # 处理 proxy 的 error proxy_intercept_errors on; error_page 415 = /assets/415.png; error_page 404 = /assets/404.png; } # 原始图片 location /_img/uploads { alias /var/www/homeland/public/uploads/$filename; expires 7d; } # 缩略图 location ~* /_img/uploads/(.+)!(large|lg|md|sm|xs)$ { set $filename /uploads/$1; if (-f $filename) { break; } # 根据 URL 地址 ! 后面的图片版原本准备好须要的参数(宽度、高度、裁剪或缩放) set $img_version $2; set $img_type resize; set $img_w -; set $img_h -; if ($img_version = 'large') { set $img_type resize; set $img_w 1920; } if ($img_version = 'lg') { set $img_type crop; set $img_w 192; set $img_h 192; } if ($img_version = 'md') { set $img_type crop; set $img_w 96; set $img_h 96; } if ($img_version = 'sm') { set $img_type crop; set $img_w 48; set $img_h 48; } if ($img_version = 'xs') { set $img_type crop; set $img_w 32; set $img_h 32; } rewrite ^ /_$img_type; } # 缩放图片的处理 location /_resize { alias /var/www/homeland/public$filename; image_filter resize $img_w $img_h; image_filter_jpeg_quality 95; image_filter_buffer 20M; image_filter_interlace on; } # 裁剪图片的处理 location /_crop { alias /var/www/homeland/public$filename; image_filter crop $img_w $img_h; image_filter_jpeg_quality 95; image_filter_buffer 20M; image_filter_interlace on; } }
你可能会以为上面为什么写得这么绕啊!
没办法,Nginx 不支持在 if {}
这个 block 里面用 image_filter
函数,image_filter 的第一个参数 resize/crop
也不能用变量的方式传输,因此...
而后,重启 Nginx,就能够尝试了。
Pragma: no-cache
的 Request Header,Nginx 会忽略 proxy_cache 从新生成图片。