4

为WordPress开启Nginx缩略图功能,七牛从此陌路

 3 years ago
source link: https://zhang.ge/5039.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
为WordPress开启Nginx缩略图功能,七牛从此陌路 | 张戈博客
Jager · 5月10日 · 2015年nginx · nginx配置 · wordpress · 七牛云存储 4368次已读

张戈博客曾分享过不少关于七牛云存储的一些经验技巧,对七牛感兴趣或者遇到相关问题的朋友可以看一看以前的相关文章:

前段时间,百度云加速自动切换到了3.0,导致我之前的一些规则出现了异常,而且在七牛cname记录上再套云加速缓存这种做法也有部分掉了链子,打开出现90x报错,只好暂时关闭云加速缓存七牛机制,结果七牛d 的数据统计就成这样了:

看来,需要采取措施才能继续享受免费服务了。本想使用之前博友建议的做法:只对需要缩略图的图片指向七牛,其他大图用源站链接,这样应该可以节省不少流量。

于是,对主题代码进行改造,只对缩略图进行七牛地址替换,其他使用源站地址,结果分享效果也不是非常明显,大概能省三分之一到一半的请求流量,但是依然做不到完全免费。

这几天公司组织外出拓展训练,我在和一个开发同事(国添)聊到了nginx时,得知Nginx还有个缩略图功能!运维不怕不会就怕孤陋寡闻,你都不知道有这么回事,也就不存在会不会了,所以不管是做运维,还是做开发,开拓的技术视野是非常重要的,不求深刻记忆,但求方向清晰。

昨天一回到家,立马进入折腾状态,学习Nginx的缩略图和缓存功能,几经折腾终于将这2个实用的功能应用到了我这个WordPress博客,博客图片从此和七牛陌路。

Ps:分享前先简单的说一说实时生成缩略图的好处。肯定有朋友会疑问,WordPress不是已经有缩略图裁剪功能了吗?而且很多主题也加入了自定义尺寸的缩略图裁剪功能,为什么还要多此一举呢?其实,用实时生成缩略图至少有如下2个好处:

①、免去上传图片被裁剪成多种尺寸的困扰(强迫症),既节省了空间且不会杂乱;

②、使用灵活,不管以后换什么主题,需要什么图片尺寸我都能随时拿出最佳尺寸。

下面开始分享具体做法。

一、模块简介

Nginx 缩略图需要用到 image_filter 模块,先贴一些基本参数,备忘之。

  • image_filter:有如下2种模式:
    ①、resize:根据尺寸比例缩放图片,比如100*100的图片,而设置是50*25,减小后的图片为25*25。如果你只想设置一个维度,可以用“-”代替。出错时返回415
    ②、crop:完全根据尺寸裁剪图片,直接裁剪成跟设置一样大小的图片。比如100*100的图片,而设置是50*25,减小后的图片为50*50,Nginx会选取中间高度25的像素,形成50*25的图片,所以图片会有缺失。如果你只想设置一个维度,可以用“-”代替。出错时返回415
  • image_filter_buffer:设置图片最大尺寸,超过设定值会返回错误页面
  • image_filter_jpeg_quality:设置jpeg图片的压缩质量比例
  • image_filter_transparency:用来禁用gif和palette-based的png图片的透明度,以此来提高图片质量

二、重新编译

因为需要用到 Nginx 的缩略图模块,所以先执行 -V 命令查看 Nginx 是否已经编译了该模块,

[root@Mars_Server ~]# /usr/local/nginx/sbin/nginx -V
Tengine version: Tengine/2.1.0 (nginx/1.6.2)
built by gcc 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC)
TLS SNI support enabled
configure arguments: --user=www --group=www --prefix=/usr/local/nginx --with-http_stub_status_module --with-http_gzip_static_module --with-http_concat_module --with-http_image_filter_module
loaded modules:
ngx_core_module (static)
ngx_errlog_module (static)

如果编译参数中找不到 http_image_filter_module,就需要重新编译 Nginx ,新增编译参数:

--with-http_image_filter_module

我现在用的是淘宝开放的 Tengine ,可以使用动态加载模块功能,如果是原版 Nginx ,可以参考张戈博客之前分享的文章,在原来的基础上加上上述参数重新编译 Nginx 即可:

Nginx在线服务状态下平滑升级或新增模块的详细操作记录

三、修改配置

URL形式①:https://zhang.ge/yuantu-${mod}300x300.jpg

Ps:${mod}表示缩略图裁剪模式,即resize或crop。

在站点的 Server 模块中新增如下 location 规则:

#resize裁剪模式配置
location ~* /(.+)-resize(d+)x(d+).(jpg|gif|png)$ {
set $width $2;
set $height $3;
#带长宽的图片实际是不存在的,所以重写到真实图片上
rewrite /(.+)-resize(d+)x(d+).(jpg|gif|png)$ /$1.$4 break;
#生成缩略图
image_filter resize $width $height;
image_filter_buffer 2M;
image_filter_jpeg_quality 80;
image_filter_transparency on;
#插入一个头部,测试中证明缩略图来自Nginx,测试无误可随时删除
add_header Thumbnail "By Nginx";
#如果找不到图片,将返回如下预设图片(请放置正确的图片)
try_files /$1.$4 /wp-content/uploads/files/notfound.jpg;
#crop裁剪模式配置
location ~* /(.+)-crop(d+)x(d+).(jpg|gif|png)$ {
set $width $2;
set $height $3;
#带长宽的图片实际是不存在的,所以重写到真实图片上
rewrite /(.+)-crop(d+)x(d+).(jpg|gif|png)$ /$1.$4 break;
#生成缩略图
image_filter crop $width $height;
image_filter_buffer 2M;
image_filter_jpeg_quality 80;
image_filter_transparency on;
#插入一个头部,测试中证明缩略图来自Nginx,测试无误可随时删除
add_header Thumbnail "By Nginx";
#如果找不到图片,将返回如下预设图片(请放置正确的图片)
try_files /$1.$4 /wp-content/uploads/files/notfound.jpg;

保存后,执行如下命令行重载 Nginx:

/usr/local/nginx/sbin/nginx -s reload

现在可以访问博客图片查看效果了,举例地址形式如下:

//res.zgboke.com/wp-content/uploads/2015/05/qiniucdn1.png

//res.zgboke.com/wp-content/uploads/2015/05/qiniucdn1-resize400x400.png

//res.zgboke.com/wp-content/uploads/2015/05/qiniucdn1-crop400x400.png

很明显的看出resize和crop的区别了吧?和七牛的2中缩略模式一摸一样,下文会有说明。

另外,带尺寸的图片地址其实是不存在的,而是 Nginx 实时生成的,我们可以通过浏览器F12开发模式,在 network 界面查看 header信息就可以看到我们插入的标识:

Ps:本来想模仿七牛的缩略图访问方式,在图片后面加上 ?w=300&h=300 请求参数来指定缩略图尺寸,可惜折腾了半天,问题总是在原图和缩略图之间徘徊,只得暂时放弃了。

URL形式①:https://zhang.ge/yuantu.jpg?w=300&h=300

这种形式是我昨天就想弄的,结果折腾半天没成功就暂时洗洗睡了,结果睡觉突然有了灵感,所以一大早就抽空搞定了,下面继续分享:

在站点的 Server 模块中新增如下 location 规则:

location ~ .*.(gif|jpg|jpeg|png|bmp)$ {
set $width '';
set $height '';
#将参数赋值给宽和高
set $width $arg_width;
set $height $arg_height;
#当存在参数请求(即请求的是缩略图),插入头部标识方便测试
if ( $width != '' ) {
add_header Thumbnail "By Nginx";
#当未设置高度时,仅使用宽度来进行缩放,可以保证图片的正常比例(适用于文章)
if ( $height = '' ) {
set $height '-';
#当请求的是原图时(即不带参数),则设置宽高维度为”-”
if ( $width = '' ) {
set $width '-';
set $height '-';
#生成缩略图
image_filter resize $width $height;
image_filter_buffer 2M;
image_filter_jpeg_quality 80;
image_filter_transparency on;

保存后,同样是执行命令行重载 Nginx,然后访问图片查看效果,比如分别访问如下2个地址:

//res.zgboke.com/wp-content/uploads/2015/05/qiniucdn1.png

//res.zgboke.com/wp-content/uploads/2015/05/qiniucdn1.png?width=480

//res.zgboke.com/wp-content/uploads/2015/05/qiniucdn1.png?width=480&height=480

可以发现和七牛一样,只要带上高宽参数就能生成想要的缩略图了,是不是很给力呢?

Ps:URL形式①和URL形式②可以同时配置到Nginx当中,不过形式②无法通过传递参数来决定resize还是crop模式,因为我测试发现 image_filter 无法将$1参数(即resize或crop)设置为变量!

不过最近发现使用URL形式①,然后再开启云加速,所有缩略图都会415报错!!

所以,对于URL形式的选择,我个人建议是:

A. 如果不用云加速,请使用形式①,因为用参数的缩略图不知道会不会搞晕搜索引擎蜘蛛呢;

B. 如果使用云加速,请使用形式②,避免大量415错误!

四、修改代码

既然 Nginx 已经准备就绪了,现在我们要做的就是修改博客的缩略图代码了,这里需要有一定的php折腾基础。因为之前的七牛缩略图就是我自己写代码实现的,所以我很轻松的完成修改,下面贴一下简单代码,仅供参考:

适用于URL形式①:

//文章缩略图及修改图片alt和标题属性函数(已删除其他多余代码)For URL形式①
add_filter ('the_content', 'content_thumbnail');
function content_thumbnail($content) {
$pattern ="/<img(.*?)src=('|")(.*?).(bmp|gif|jpeg|jpg|png)('|") alt="(.*?)"(.*?)>/i"; //注释之前文章页面的七牛缩略图关键代码: //$replacement2='<img$1src=$2$3.$4?imageMogr2/thumbnail/380x$5 alt="'.$post->post_title.'" tilte="'.$post->post_title.'"$7>'; //改成如下即可,代码为480大小(resize模式) $replacement='<img$1src=$2$3-resize480x480.$4$5 alt="'.$post->post_title.'" tilte="'.$post->post_title.'"$7>'; //排除不需要缩略图的文章(通过给图片设置nosuolvetu的alt属性) if(!preg_match_all('/nosuolvetu/i',$content,$matches)) { $content=preg_replace($pattern, $replacement, $content); } return $content; }

适用于URL形式②:

//文章缩略图及修改图片alt和标题属性函数(已删除其他多余代码)For URL形式②
add_filter ('the_content', 'content_thumbnail');
function content_thumbnail($content) {
$pattern ="/<img(.*?)src=('|")(.*?).(bmp|gif|jpeg|jpg|png)('|") alt="(.*?)"(.*?)>/i";
//注释之前文章页面的七牛缩略图关键代码:
//$replacement2 = '<img$1src=$2$3.$4?imageMogr2/thumbnail/380x$5 alt="'.$post->post_title.'" tilte="'.$post->post_title.'"$7>';
#改成如下即可
$replacement = '<img$1src=$2$3.$4?width=480&height=480$5 alt="'.$post->post_title.'" tilte="'.$post->post_title.'"$7>';
//排除不需要缩略图的文章(通过给图片设置nosuolvetu的alt属性)
if(!preg_match_all('/nosuolvetu/i',$content,$matches)) {
$content = preg_replace($pattern, $replacement, $content);
//去掉原有的图片大小定义,避免图片模糊
$content = preg_replace('/<img(.*?)width="(.*?)" height="(.*?)"(.*?)>/i', '<img$1$4>', $content);
return $content;

当然,这只是文章缩略图,其他位置的缩略图就需要修改主题代码了,由于每个主题都不一样,所以本文就不赘述了,相信这对懂得折腾的人来说应该是小菜一碟了。

五、拓展延伸

细心的朋友可以发现这个缩略图模块有2种模式:resize 和 crop ,前者是比例缩放,后者则是尺寸裁剪。比例缩放的优点是最大程度保持图片的完整性,缺点则是如果图片的宽或高小于指定尺寸,生成的缩略图可能就会空白一部分,因为要保持缩放比例;尺寸裁剪的优点就是能保证缩略图不会出现空白区域。但是通常因为会剪掉多出的部分,也就无法保证图片内容的完整性了。

这样解释可能还是有点模糊,具体可以参考下七牛的缩略图API的2种裁剪模式:

另外发现,还有其他的Nginx缩略图模块,比如国人开发的 ngx_image_thumb,还支持添加水印等其他更强大的缩略图功能,感兴趣的童鞋可以去折腾研究下。

六、下篇预告

完成以上步骤,博客终于不再需要七牛来实现缩略图功能了。当然,由于这个模块并不会产生真实的缩略图片,所以访问量很大时消耗CPU会很明显。

针对这个情况,张戈博客已经给 Nginx 启用了缓存机制,生成的缩略图将缓存到本地磁盘当中,下次访问直接调取,从而解决了实时生成图片带来的CPU问题(可从上文 浏览器开发模式当中看到 X-Cache:HIT from zhang.ge 标识)。

具体操作,敬请期待下一篇分享,还有直接缓存 html 伪静态页面功能哦!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK