Nginx笔记(五)----Nginx+Lua+GraphicsMagick实现图片自动裁剪/缩放、以及定时清理生成的缩略图

本文介绍如何利用Nginx配合Lua及GraphicsMagick实现实时图片裁剪功能,包括安装配置过程及测试方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前言

在开发的过程中,在后台提交的图片没有做什么处理,然后APP,前端页面,获取到图片之后,自己通过控制宽高实现对图片的控制,在这种情况下,会出现,一张图片很大,原封不动的返回给客户端,浪费服务器带宽,请求响应变慢。这个时候我们就要在服务器端对图片进行处理,根据客户端的请求参数,返回相应的图片。

面临的问题
    ● 网站需求变更,需要更多不同尺寸的缩略图
    ● 有些图片的缩略图很少使用到,但还是存在了硬盘上,造成空间浪费

需求

   ● 根据请求参数动态裁剪图片保存到本地,裁剪后的图片和原图放在同一级目录

        例如原图地址的物理路径为:/static/images/uploads/2016/07/01.jpg

        按200x200裁剪后的图片物理路径为:/static/images/uploads/2016/07/01_200x200.jpg

   ● 只在第一次请求时裁剪,后面不裁剪,从本地取图片,如果本地没有图片再裁剪图片返回。

   ● 定时清理目录下的裁剪图,减少硬盘空间。

   ● 根据坐标裁剪图片中的某一块区域。

解决方法

由于我这里图片处理用的是nginx,所以,有以下两种解决方法:

1.Nginx自带的http_image_filter_module模块

2.Nginx搭配Lua+GraphicsMagick

Nginx 虽然有自带的 image filter module 实现此功能,但是有弊端:

● image filter module 使用的是 GD,GD 性能、效率、处理后的图片质量不如 GraphicsMagick、并且裁剪后也不会保存,这样每次请求过来都要重新裁剪,所以访问很慢。

● image filter module 没法真正生成裁剪/缩放后的图片,而是通过 Nginx 直接输出的,这样每次请求或缓存过期后都需要重新裁剪/缩放,这样无疑会增加 Nginx 负担

这里使用Lua+GraphicsMagick实现图片自由裁剪、把裁剪后的图片放到一个目录,并做好过期或定期删除,访问时就去判断,有裁剪后的就取,没有的再做裁剪。

但是这样也有个问题就是,用久了之后,会在本地硬盘产生很多缩略图,对硬盘造成浪费,所以需要定时的清理硬盘下的缩略图。

如果用Nginx来处理图片的话,就会有以下的优缺点:

▲ 优点

     ● 操作简单。通过简单配置,省去了后端裁剪程序的复杂性。
     ● 实时裁剪。可以实时访问在线裁剪图片。
     ● 灵活性强。后端程序裁剪图片时需要知道裁剪图片的尺寸和质量,使用nginx裁剪可以实时裁剪任意尺寸的图片。

不占用硬盘空间。

▲ 缺点
    ● 消耗CPU和内存,访问量大的时候就会给服务器带来很大的负担。(可以通过使用Nginx缓存和缓存服务器来解决)

    ● 功能不是很强大,支持的处理图片类型只包括JPEG, GIF, PNG, or WebP

二、搭建

由于我这里是先安装好了Nginx,所以就不安装Nginx了,用的版本是nginx/1.7.4,只安装一些必要的模块,步骤如下:

2.1、基础软件包安装

# yum -y install epel-release git
# yum install -y gcc gcc-c++ zlib zlib-devel openssl openssl-devel pcre pcre-devel
# yum install -y libpng libjpeg libpng-devel libjpeg-devel ghostscript libtiff libtiff-devel freetype freetype-devel readline-devel ncurses-devel libtermcap-devel ncurses-devel libevent-devel

2.2、下载相关软件

# cd /usr/local/src
# wget http://luajit.org/download/LuaJIT-2.0.4.tar.gz
# wget http://www.zlib.net/fossils/zlib-1.2.8.tar.gz
# wget http://www.lua.org/ftp/lua-5.3.1.tar.gz  
# wget ftp://ftp.graphicsmagick.org/pub/GraphicsMagick/1.3/GraphicsMagick-1.3.18.tar.gz

# yum install git
# git clone https://github.com/simpl/ngx_devel_kit.git
# git clone https://github.com/openresty/lua-nginx-module.git
# git clone https://github.com/simpl/ngx_devel_kit.git

2.3、编译安装Lua、GraphicsMagick

# tar -zxf LuaJIT-2.0.4.tar.gz
# tar -zxf zlib-1.2.8.tar.gz
# cd LuaJIT-2.0.4
# make 
# make install 
# export LUAJIT_LIB=/usr/local/lib
# export LUAJIT_INC=/usr/local/include/luajit-2.0
# ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2
  
# cd ..
# tar -zxvpf lua-5.3.1.tar.gz
# cd lua-5.3.1
# make linux && make install
  
# cd ..
# tar -zxvpf GraphicsMagick-1.3.18.tar.gz
# cd GraphicsMagick-1.3.18
# ./configure --prefix=/usr/local/GraphicsMagick --enable-shared
# make  && make install

2.4、Nginx动态添加模块

先查看nginx编译安装时安装了哪些模块

# nginx -V
nginx version: nginx/1.7.4
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-16) (GCC)
TLS SNI support enabled
configure arguments: 
--prefix=/usr/local/nginx 
--with-pcre=/root/pcre-8.35 
--with-zlib=/root/zlib-1.2.8 
--with-openssl=/root/openssl-1.0.1i 
--with-http_ssl_module 
--with-http_sub_module 
--with-http_stub_status_module 

2.5、加入需要安装的模块,重新编译,在nginx的源码目录下,通过–add-module=xxx的方式添加以下模块

--add-module=/usr/local/src/lua-nginx-module
--add-module=/usr/local/src/ngx_devel_kit
完整的如下
./configure --prefix=/usr/local/nginx --with-pcre=/root/pcre-8.35 --with-zlib=/root/zlib-1.2.8 --with-openssl=/root/openssl-1.0.1i --with-http_ssl_module --with-http_sub_module --with-http_stub_status_module --add-module=/usr/local/src/lua-nginx-module --add-module=/usr/local/src/ngx_devel_kit

然后

# make    //千万不要make install,不然就真的覆盖了

然后可以通过nginx -V查看是否添加成功

2.6、替换nginx二进制文件,在nginx源码目录下执行以下命令

# cp /usr/local/nginx/sbin/nginx /usr/local/nginx/sbin/nginx.bak
# cp ./objs/nginx /usr/local/nginx/sbin/

2.7、修改nginx配置文件

首先测试看能否访问图片:

location ~ .*\.(gif|jpg|jpeg|png)$ {    
	expires 24h;    
		root /home/nginx/html/;#指定图片存放路径  
		access_log /usr/local/nginx/logs/images.log;#日志存放路径    
		proxy_store on;    
		proxy_store_access user:rw group:rw all:rw;    
		proxy_temp_path         /usr/local/nginx/html;#图片访问路径    
		proxy_redirect          off;    
		proxy_set_header        Host 19;    
		client_max_body_size    10m;    
		client_body_buffer_size 1280k;    
		proxy_connect_timeout   900;    
		proxy_send_timeout      900;    
		proxy_read_timeout      900;    
		proxy_buffer_size       40k;    
		proxy_buffers           40 320k;    
		proxy_busy_buffers_size 640k;    
		proxy_temp_file_write_size 640k;    
		if ( !-e $request_filename)    
		{    
			 proxy_pass  http://127.0.0.1;#默认80端口    
		}    
}      
location / {  
  root  /home/nginx/html; #html访问路径 
  index index.html; #html文件名称 

} 

在html下上传图片然后访问: http://192.168.182.5/2018.jpeg


然后将上面的location匹配的图片改成如下所示:

location / {
		root   /home/nginx/html;
		index  index.html index.htm;
}

location ~* ^((\/manager)(\/\w+)(.+\.(jpg|jpeg|gif|png))_(\d+)x(\d+)\.(jpg|jpeg|gif|png))$ {
                root /home/nginx/html;
                if (!-f $request_filename) {    # 如果文件不存在时才需要裁剪
					add_header X-Powered-By 'Lua GraphicsMagick';    # 此 HTTP Header 无实际意义,用于测试
					add_header file-path $request_filename;    # 此 HTTP Header 无实际意义,用于测试
					#lua_code_cache off; # 在编写外部 Lua 脚本时,设置为 off Nginx 不会缓存 Lua,方便调试
					set $request_filepath /home/nginx/html$2/$3/$4;    # 设置原始图片路径,如:/manager/app/2018.jpeg
					set $width $6;    # 设置裁剪/缩放的宽度
					set $height $7;    # 设置裁剪/缩放的高度
					set $ext $5;    # 图片文件格式后缀
					content_by_lua_file lua/ImageResizer.lua;    # 加载外部 Lua 文件
                 }
}

其中的:

location / {
		root   /home/nginx/html;
		index  index.html index.htm;
}

匹配如下请求: 

http://192.168.182.5/2018.jpeg 

● 黄颜色的用来匹配:

http://192.168.182.5/manager/test/2014.jpeg_100x100.jpeg

这种请求。

● 红颜色root指定当前server的根目录,对应系统上的具体文件夹

● 绿颜色是设置ngx变量,变量值就是正则匹配的$匹配组的值,设置好变量后可以在lua脚本中使用


注意:

我在这里遇到了一些坑。。。上面的这个正则:

~* ^((\/manager)(\/\w+)(.+\.(jpg|jpeg|gif|png))_(\d+)x(\d+)\.(jpg|jpeg|gif|png))$

是用来匹配像我这种路径:

http://192.168.182.5/manager/test/2014.jpeg_100x100.jpeg

可以通过在线正则工具来检查:


注意要去掉前面的~*。

正则:

1、^: 匹配字符串的开始位置;
2、 $:匹配字符串的结束位置;
3、.*:   .匹配任意字符,*匹配数量0到正无穷;
4、\. 斜杠用来转义,\.匹配 .    特殊使用方法,记住记性了;
5、(值1|值2|值3|值4):或匹配模式,例:(jpg|gif|png|bmp)匹配jpg或gif或png或bmp

^ 匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配 ^ 字符本身,请使用 \^。
$ 匹配输入字符串结尾的位置。如果设置了 RegExp 对象的 Multiline 属性,$ 还会与 \n 或 \r 之前的位置匹配。
\. 斜杠用来转义,\.匹配.
[\w+]表示匹配数字、字母、下划线和加号本身字符
location ~* .(gif|jpg|jpeg)$ {
# 匹配任何已.gif、.jpg 或 .jpeg 结尾的请求
+ 匹配前面的子表达式一次或多次。要匹配 + 字符,请使用 \+。

我在这里调试了很久。。。可通过如下方式来调:

location ~* ^((\/manager)(\/\w+)(.+\.(jpg|jpeg|gif|png))_(\d+)+x(\d+)+\.(jpg|jpeg|gif|png))$ {
        set $para1 $1;
        set $para2 $2;
        set $para3 $3;
        set $para4 $4;
        set $para5 $5;
        set $para6 $6;
        set $para7 $7;
        set $para8 $8;
        set $para9 $9;
        content_by_lua_block {
                ngx.say(ngx.var.para1)
                ngx.say(ngx.var.para2)
                ngx.say(ngx.var.para3)
                ngx.say(ngx.var.para4)
                ngx.say(ngx.var.para5)
                ngx.say(ngx.var.para6)
                ngx.say(ngx.var.para7)
                ngx.say(ngx.var.para8)
                ngx.say(ngx.var.para9)
        }

}

打印在浏览器上如下:

/manager/test/2014.jpeg_100x100.jpeg
/manager
/test
/2014.jpeg
jpeg
100
100
jpeg

然后把打印值的变量修改到如下地方:

set $request_filepath /home/nginx/html$2/$3/$4;    # 设置原始图片路径,如:/manager/app/2018.jpeg
set $width $6;                                     # 设置裁剪/缩放的宽度
set $height $7;                                    # 设置裁剪/缩放的高度
set $ext $5;                                       # 图片文件格式后缀

2.8、创建lua脚本

在/usr/local/nginx/lua/目录下创建ImageResizer.lua文件

# cat /usr/local/nginx/lua/ImageResizer.lua 
local command = "/usr/local/GraphicsMagick/bin/gm convert   -auto-orient -strip " .. ngx.var.request_filepath .. " -resize " .. ngx.var.width .. "x" .. ngx.var.height .. " +profile \"*\" " .. ngx.var.request_filepath .. "_" .. ngx.var.width .. "x" .. ngx.var.height .. "." .. ngx.var.ext;
os.execute(command);    
ngx.exec(ngx.var.request_uri);

三、测试

然后通过命令重新加载Nginx配置文件

[root@fendo sbin]# ./nginx -s reload

访问以下连接:

http://192.168.1.5:7501/manager/test/2014.jpeg

效果如下所示:



然后再访问:

http://192.168.1.5:7501/manager/test/2014.jpeg_100x100.jpeg

效果如下所示



同时会在manager/test目录下多出个2014.jpeg_100x100.jpeg的图片。


最后就是通过脚本定时删除生成的图片了。


参考:

http://www.cnblogs.com/xy-nb/articles/Nginx-Lua-GraphicsMagick.html

http://www.hopesoft.org/blog/?p=1188

http://yanue.net/post-166.html


图片批量裁剪(精华版)是 一款功能丰富、实用、应有尽有的图片/视频批量裁剪、水印、转换、更名,以及其他处理的专业工具!批量处理时不低于5万个文件。 以管理员身份和兼容xp3模式下运行,可支持win7,win8,win10,64位。 图片批量裁剪(精华版)功能 1. 支持常见图片类型如bmp,jpg,tif,gif,png,支持部分非常见图片类型,如PSD,PCX,ICO,Pdf,动态Gif等等;支持对大多数常见的音频/视频文件格式的裁剪、转换、水印、分割、合并等; 2.提供对图片文件的丰富多彩实用的各种批量裁剪模式,如相对、绝对、固定、大小、等分/非等分分切、分隔、同比/非同比缩放、拼接/无缝拼合、贴边等等几百种裁剪处理功能; 支持圆角矩形/椭圆形/圆形/任意角度裁剪,支持自定义圆角矩形半径裁剪; 3.其他更丰富的裁剪功能,请参见主页说明或程序,比如:提取图片上的文字并保存先裁剪后加水印一步到位忽略处理过的文件夹手动指定裁剪区域多裁剪区域裁剪打印二维码图片转Pdf 过滤小图或缩略图 AB文件夹配对拼合 …… 内置其他功能列表: 1.图片烙制水印(文字水印,图片水印,淘宝卖家专用水印,以及其他上百种水印功能模式供选择,特别如以拍摄日期作为文字水印,递增数字水印等等,批量制卡证等) 2.图片旋转及格式转换(特别功能如智能扳正) 3.图片亮度/对比度调整 4.图片压缩(特色功能如保留Exif信息的压缩) 5.定制图片大小/尺寸(特色功能如能按指定的文件大小压缩,比如压缩到120kb左右,仅压缩大图,小图忽略压缩等) 6.图片像素筛查(从海量图片中筛查出满足条件的图片供删除、移动、复制、更名等) 7.(图片)文件时间属性修改(比如更改拍摄日期,没有做不到只有想不到) 8.图像综合处理 9.(图片)文件批量更名(强大丰富的多种文件批量更名功能) 10.文件随机/顺序/定时抽取分发(将海量文件复制或移动到指定的文件夹中) 11.证件照批量更换背景颜色 12.色块/色条魔术棒裁剪,颜色替换 13.音视频裁剪/分割/合并/转换/加水印/录音/录像 14.批量替换图片中的图片或文字 15.图像批量组合排版 16.证件制作排版(广告公司实用) 17.Jpg图片Exif信息编辑器 18.重复或相似图片批量查找 19.相对/绝对/固定裁剪简易兼容备用版 20.Jpg转视频avi或其他(影楼后期制作DV工具) 21.图片批量浏览挑拣器(影楼客户自选照片实用) 22.图片批量叠加/混合 23.视频批量加密(特色功能如用户可自行在线找回播放密码,一机一码,一视频一码) 24.账号、密码批量管理小秘书(管理你各种账号密码,完全安全加密) 25.动态Gif图片裁剪、水印;图片压制成动态Gif(按时间轴裁剪裁剪后的gif仍然是动画模式) 26.音频片段截取助手 27.广告喷绘大图专用分切器(喷绘行业专用) 图片批量水印裁剪器 v6.0.20161008精华版更新内容: 1.新增动态Gif水印区域批量涂抹模糊,或者图片水印区域批量涂抹功能; 2.修正水印添加模块中,还原或重设DPI功能时失效异常的问题; 3.在水印批量添加模块中,新增还原原图DPI以及转为CMYK印刷颜色模式的新功能; 4.新增批量生成二维码图片的功能; 5.新增图片裁剪/缩放/格式转换/添加水印等单张综合处理功能模块; 6.修正先选择后裁剪功能实现的问题; 7.新增批量对动态Gif文件指定水印区域模糊化处理功能; 8.新增定时对指定的目录中的图片挂机无人值守自动裁剪功能,忽略已处理过的图片文件; 9.新增纯文字水印添加功能模块; 10.新增学生证件照排版和学生胸卡排版制作打印功能模块; 11.改进修正Jpg系列图片转视频功能,并新增同时给转换后的视频叠加音频的功能; 12.修正改进动态Gif裁剪、水印功能模块; 13.改进跟图片OCR文字识别的有关问题和功能; 14.新增备用下载服务器和网络登录版; 15.修正精确去片头片尾功能; 16.修正某些音频视频文件播放时间不足一秒时无法加载入文件列表的异常; 17.修正媒体批量合并功能模块全部失效的问题; 18.新增以文件夹名作为动态文字水印的功能。 图片批量裁剪(精华版)截图
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值