你還在用 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 從新生成圖片。