Cấu hình Nginx để resize hoặc crop image

by Thien

on Sep 26/16 at 07:29

Giới thiệu

Có bao giờ bạn tự hỏi mấy trang web lớn nó xử lý resize hay crop hình ảnh như thế nào không, ví dụ trang youtube https://i.ytimg.com/vi/8fmzq-8z1bA/hqdefault.jpg?custom=true&w=196&h=110&stc=true&jpg444=true&jpgq=90&sp=68&sigh=YRcoYPsPtTEhspq7DaLtzXeFjrE, bạn hãy để ý các tham số ở sau hqdefault.jpg ta có thể dễ dàng dùng Nginx để làm điều đó mà cụ thể là module ngx_http_image_filter_module. Vì vậy trong bài viết này tôi sẽ hướng dẫn bạn làm điều đó

Cài đặt

Trước tiên ban cần phải đặt nginx trên OS của bạn với centos bạn chỉ cần chạy lệnh sau:

yum install nginx -y

Sau đó bạn cần cài module ngx_http_image_filter_module vì mặt định Nginx không có cài nó, để cài đặt nó chỉ cần chạy lệnh sau:

yum install nginx-mod-http-image-filter.x86_64 -y

Chú ý rằng nếu bạn không tìm thấy module bạn có thể dùng lệnh dưới đây để tìm nó

yum search nginx | grep nginx-mod-http
nginx-mod-http-image-filter.x86_64 : Nginx HTTP image filter module

Cấu hình bộ lọc hình ảnh

Một cấu hình đơn giản cho việc chuyển đổi một định dạng jpg thành thumbnail với kích thước 150 * 150 như sau:

location ~ /images/.*\.jpg$ {
    image_filter  crop  150  150;
}

Mở rộng hơn, chúng ta sẽ cấu hình với tính năng resize hoặc crop hình ảnh theo các bước như sau :

  1. Chúng ta kiểm tra sự hiện diện của các thông số được truyền vào, nếu không có, chúng ta phải trả lại hình ảnh bình thường
location ~ /images/.*\.jpg$ {
    if ($query_string ~ .*=.*) {
      rewrite ^/images/(.*\.jpg)$ /image_filter/$1 last;
    }
}
  1. Kế tiếp, chúng ta sẽ kiểm tra thông số truyền vào là resize hay là crop, mặc định nếu không có thông số truyền vào là crop :
if ($arg_type = "resize") {
    rewrite ^ /resize last;
}

rewrite ^ /crop last;
  1. Ứng với resize hay crop, hình ảnh được chuyển đổi sẽ được trả về.
image_filter resize $width $height;
image_filter crop $width $height;

Trong trường hợp bộ lọc hình ảnh không xử lý được, lỗi 415 sẽ xảy ra, vì vậy chúng ta nên thay thế bằng 1 hình ảnh GIF có kích thước 1 * 1 px.

Dưới đây là một cấu hình hoàn chỉnh với bộ lọc hình ảnh :

server {
    # Basic image resizing server, no caching.
    server_name ama.phanbook.com;
    root /usr/share/nginx/html/images/;

    location ~ /images/.*\.jpg$ {
        if ($query_string ~ .*=.*) {
          rewrite ^/images/(.*\.jpg)$ /image_filter/$1 last;
        }
    }

    location ~ ^/image_filter/(.*\.jpg)$ {
        internal;

        set $file $1;
        set $width 150;
        set $height 150;
        set $quality 75;

        if ($arg_width ~ (\d*)) {
            set $width $1;
        }
        if ($arg_height ~ (\d*)) {
            set $height $1;
        }
        if ($arg_quality ~ (100|[1-9][0-9]|[1-9])) {
            set $quality $1;
        }

        if ($arg_type = "resize") {
            rewrite ^ /resize last;
        }

        rewrite ^ /crop last;
    }

    location /resize {
        internal;
        rewrite ^ /images/$file break;
        image_filter  resize  $width $height;
        image_filter_jpeg_quality $quality;
        error_page 415 = @empty;
    }

    location /crop {
        internal;
        rewrite ^ /images/$file break;
        image_filter  crop  $width $height;
        image_filter_jpeg_quality $quality;
        error_page 415 = @empty;
    }

    location @empty {
        empty_gif;
    }
}

Ok, bây giờ bạn chỉ cần tạo file đó trong thư mục của Nginx sau đó khỏi động lại

service nginx restart

Kiểm tra kết quả

Bạn có thể truy cập đương dẫn này đế test

http://ama.phanbook.com/images/abc.jpg?width=500&height=150&type=resize
http://ama.phanbook.com/images/abc.jpg?width=500&height=150&type=crop
http://ama.phanbook.com/images/abc.jpg?width=400&height=400&type=crop&quality=110

Chú ý rằng trong cấu hình trên chúng tôi chưa có lưu cache cho mỗi lần request từ url do đó khi bạn apply lên trang production thì nên bật cache lên để đảm bảo tối đa tốc độ website của bạn

Mở rộng trường hợp xa hơn là bạn dùng Nginx để fillter hình ảnh từ máy chủ Amazon s3 và bảo vệ resource của bạn thì bạn có thể cấu hình nó dễ dàng, xem tại đây https://coderwall.com/p/rlguog/nginx-as-proxy-for-amazon-s3-public-private-files

Kết luận

Bằng việc sử dụng bộ lọc hình ảnh với Nginx, chúng ta có thể thay đổi kích thước và chất lượng của hình ảnh sao cho phù hợp với yêu cầu mà website đề ra, cũng như hiển thị hình ảnh trên những thiết bị Android hay Iphone với những kích cỡ khác nhau, qua đó nó giúp chúng ta cải thiện được tốc độ khi lướt web.

Ngoài ra bạn cũng có thể dùng go để làm chuyện đó xem thêm tại đây https://github.com/willnorris/imageproxy