Using ngx_http_image_filter_module of Nginx to make real-time picture thumbnails

Keywords: Nginx sudo Ruby curl

You're still using it. ImageMagick Create thumbnails of uploaded pictures on the website? In fact, there are better ways to put one in place, simple and effective.

Nowadays, there are many cloud storage services supporting image space, and according to the set rules to generate image thumbnails in the space, such as UpYun, Aliyun OSS support.

But sometimes we choose local files to store and upload files because of some other considerations (such as price factor). At this time, how can we implement image thumbnails?

In fact, Nginx is built-in. ngx_http_image_filter_module Help you deal with pictures:

  • zoom
  • Tailoring
  • Adjust picture quality
  • rotate
  • sharpening

We often use scaling and tailoring, thumbnails of different sizes in the right place according to business and design needs.

install

Maybe some standard Nginx installation packages don't have this module. You need to use the official source installation of Nginx and install the nginx-module-image-filter package in addition:

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

It can also be used directly. set up script

curl -sSL https://git.io/vVHhf | bash

scene

Taking the Ruby China scenario as an example, I designed the following different thumbnail versions:

Version name Limited size (px) Abbreviation
large 1920 Width-limited, height-adaptive
lg 192x192 Fixed width and height
md 96x96 Fixed width and height
sm 48x48 Fixed width and height
xs 32x32 Fixed width and height

Configure Nginx

Suppose our uploaded files are stored in / var/www/homeland/public/uploads.

The following is the complete Nginx configuration of Ruby China, a thumbnail rule:

/etc/nginx/nginx.conf

user nobody;
worker_processes auto;
pid /var/www/pids/nginx.pid;
daemon on;

# Load ngx_http_image_filter_module
load_module modules/ngx_http_image_filter_module.so;

http {
   # ... omission
}

/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 adds the hit status of proxy_cache for later debugging and problem checking
    add_header X-Cache-Status $upstream_cache_status;

    proxy_pass http://127.0.0.1/_img/uploads;
    # Cache thumbnails in services to avoid regeneration of each request
    proxy_cache uploads_thumb;
    # Ignore proxy_cache when receiving HTTP Header Pragma: no-cache
    # This configuration allows browsers to regenerate thumbnails by ignoring proxy_cache when forced to refresh
    proxy_cache_bypass $http_pragma;
    # Since Upload files generally have no parameters, host + document_uri has been used as
    proxy_cache_key "$host$document_uri";
    # Valid files, cached on server for 7 days
    proxy_cache_valid 200 7d;
    proxy_cache_use_stale error timeout invalid_header updating;
    proxy_cache_revalidate on;
    # Processing error of proxy
    proxy_intercept_errors on;
    error_page   415 = /assets/415.png;
    error_page   404 = /assets/404.png;
  }

  # Original picture
  location /_img/uploads {
    alias /var/www/homeland/public/uploads/$filename;
    expires 7d;
  }

  # thumbnail
  location ~* /_img/uploads/(.+)!(large|lg|md|sm|xs)$ {
    set $filename /uploads/$1;

    if (-f $filename) {
      break;
    }

    # Prepare the required parameters (width, height, cropping or zooming) according to the URL address!
    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;
  }

  # Processing of Scaled Pictures
  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;
  }

  # Processing of clipped pictures
  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;
  }
}

You may wonder why it's so roundabout.

No way, Nginx doesn't support using image_filter function in if {} block. The first parameter of image_filter, resize/crop, can't be transferred by variables either. So uuuuuuuuuuuu

Then, restart Nginx and try.

Attention points

  • Since the proxy_cache thumbnail will exist as a file on the server, you need to make sure that every time you upload a new file name, it is as unique as possible (e.g. using time, or MD5 as the file name, for reference). Design of CarrieWave File Name)
  • When the browser refreshes forcibly, the Pragma: no-cache Request Header will be launched, and Nginx will ignore the proxy_cache to regenerate the image.

Effect demonstration

 

Extended reading

Posted by skatermike21988 on Wed, 12 Dec 2018 22:36:07 -0800