网站建设

WordPress集成PHP缩略图,并开启Nginx缓存的方法

Jager · 6月25日 · 2015年 · · · · 4730次已读

之前张戈博客分享过一篇给 WordPress 开启 Nginx 缩略图的教程,用着确实不错!但是总感觉清晰度不敢恭维,就算将裁剪质量调到 90 依然失真严重,于是想另辟蹊径。

想起之前帮一个站长做 CC 防御的时候,发现他的网站就算被纯静态化,被攻击时 CPU 依然狂飙。最后分析请求日志发现,所有的压力来自网站的 PHP 缩略图功能。这个 PHP 缩略图虽然可以将实时生成的图片缓存成文件,但是第二次被请求,PHP 依然需要进行一些很简单的判断,比如这个缩略图是否被缓存、缓存文件是否过期等。在海量 IP 的请求下,这些简单的 PHP 动态判断就成为了拖沓大户了!

这也就不难理解 WP-Super-Cache 的 php 缓存模式比 Mod_Rewrite 模式要慢的原因了!所以,静态缓存最终都要完全抛弃掉任何简单计算才能算是淋漓尽致!

WordPress集成PHP缩略图,并开启Nginx缓存的方法

好了,扯得有点远了。虽然这位站长同学后来抛弃了这个 PHP 缩略图功能,但是张戈却记忆深刻。当  Nginx 缩略图不给力时,我第一时间就想到了它。

这玩意在访问量过大时是个拖沓大户,但如果我想办法去掉其中的 PHP 动态判断呢?自然就能发挥到淋漓尽致了!

下面简单分享下张戈的做法。

一、加速思路

我顺藤摸瓜(之前那位站长朋友用的就是倡萌的 Wdone 主题),自然就在倡萌那找到了这个 PHP 缩略图的使用方法:

<img src="http://timthumb 所在目录/timthumb.php?src=图片地址&h=图片高度&w=图片宽度&zc=1" class="thumb" />

可以看到,这种传参肯定是存在动态判断的,所以要完全静态化,我首先就要修改这个缩略图形式。

很简单,延续之前分享的 Nginx 缩略图思路,把上面的 url 改成在图片地址最后带参数的模式,然后伪静态重写为上面的形式,最后通过 Nginx 实现纯静态缓存

二、部署方法

①、PHP 代码

下载后解压得到 thumb 文件夹,编辑里面的 timthumb-config.php,按照注释修改下(可选)。

然后将整个文件夹上传到网站根目录,现在按照倡萌给出的 url 形式肯定就可以看到缩略图了。

②、Nginx 规则

第①步能够正常看到缩略图效果后,我们接着部署 Nginx 规则。

在网站原有的 Nginx 规则中插入如下规则:

#Nginx 重写 PHP 缩略图 URL 规则 By 张戈博客
location ~ .*\.(gif|jpg|jpeg|png|bmp)$ {
      set $width '';
      set $height '';
      set $width $arg_w;
      set $height $arg_h;
      #只要图片带上宽度(?w=)或高度(?h=)参数,都会将访问重写到/thumb/?src=* 这个动态缩略图生成的接口上
      if ( $width != '' ) {
           rewrite ^(.*)$ /thumb/?src=http://$host/$1 last;
      }
      if ( $height != '' ) {
           rewrite ^(.*)$ /thumb/?src=http://$host/$1 last;
      }
      expires  max;
}

这样还只是重写了缩略图的 URL 形式,如果需要开启缓存,则需要用到 Nginx 的 fastcgi 缓存,还不熟悉的朋友请先参考张戈博客之前的分享:

Nginx 开启 fastcgi_cache 缓存加速,支持 html 伪静态页面

按照之前的文章部署 fastcgi 缓存规则后,这个缩略图就被 Nginx 缓存了(在 F12 开发者模式中查看 network 头部信息即可看到 HIT from yourdomain.com),加载速度自然也就上来了!

三、主题修改

做完上述操作之后,还只是具备了这个缩略图功能,而实际应用到博客文章,总不能手工一个一个输入图片带上尺寸吧?而且还有一堆老文章也不可能人工修改一遍吧?

实际解决很简单,请参考如下代码:

add_filter ('the_content', 'content_thumbnail');
function content_thumbnail($content) {
        global $post;
        $pattern1 ="/<img(.*?)src=('|\")(.*?).(bmp|gif|jpeg|jpg|png)('|\") alt=\"(.*?)\"(.*?)>/i";
        $pattern2 ="/<img(.*?)src=('|\")(.*?)-300x(\d+?).(bmp|gif|jpeg|jpg|png)('|\")(.*?)>/i";
        $pattern3 ="/<img(.*?)src=('|\")(.*?)-(\d+?)x300.(bmp|gif|jpeg|jpg|png)('|\")(.*?)>/i";
        $replacement = '<img$1src=$2$3.$5$6$7>';
        $replacement2 = '<img$1src=$2$3.$4?w=480$5 alt="'.$post->post_title.'" tilte="'.$post->post_title.'"$7>';
        $content = preg_replace($pattern2, $replacement, $content);
        $content = preg_replace($pattern3, $replacement, $content);
        $content = preg_replace($pattern1, $replacement2, $content);
        $content = preg_replace('/<img(.*?)width="(.*?)" height="(.*?)"(.*?)>/i', '<img$1$4>', $content);
	return $content;
}

修改原理:

①、将老文章中带尺寸的图片改成完整图片路径,我之前用的是 300 大小的图片缩略图,所以这里需要将高或宽 300 的全部去掉,变成完整尺寸图片路径;

②、最后将文章中所有图片路径上带上适合本文分享的尺寸规则,比如上述代码是?w=480,即图片缩略图统一改为 480px 大小。

好了,就分享这么多,有需求的朋友可以参考上面的代码,根据实际情况修改后加入到主题 functions.php 即可完美实现文章缩略图了。

40 条回应
  1. 软件海 2015-6-26 · 1:51

    首先表示支持,另外,我上传的特色图就是按照自动裁剪的尺寸上传的,那么,系统还会再次生成缩略图吗?

    • avatar
      Jager 2015-6-26 · 8:18

      文章的目的就是杜绝一张图片上传被裁剪成多个尺寸,不但占用空间,而且一旦换主题,缩略图尺寸需求又不一样了,非常恶心。

      • 西贝博客 2015-6-28 · 9:23

        这一点的确是这样,以前饱受痛苦。。

  2. 西贝博客 2015-6-28 · 9:22

    这个缩略图和特色图片会产生冲突吗?

    • avatar
      Jager 2015-6-29 · 8:16

      不会

  3. Andrew 2015-6-28 · 11:29

    学习了

  4. 逍遥乐 2015-6-29 · 22:12

    这个方法与七牛镜像存储有没有冲突

    • avatar
      Jager 2015-6-29 · 23:52

      是带参数的相同路径,应该有冲突。
      估计大图小图傻傻分不清楚。

  5. af 2015-6-30 · 11:52

    谢谢博主分享,已经下载~

  6. 黄勇博客 2015-6-30 · 14:15

    一直在为自己的懒惰找借口,一直抱着浮躁和狂妄的心态去做事。事情做好了就炫耀是能力,做差了就借口是运气不好。

  7. 热词网 2015-6-30 · 17:02

    签到成功!签到时间:下午5:01:01,每日签到,生活更精彩哦~

  8. 筛宝 2015-7-1 · 9:24

    缓存后会更快。

  9. Nhzy资讯君 2015-7-1 · 12:45

    感谢流量不大没必要折腾

    • avatar
      Jager 2015-7-1 · 19:32

      不折腾你就学不到

  10. 硅藻泥缺点 2015-7-1 · 15:13

    :wink:路过点赞

  11. 必分享 2015-7-1 · 15:57

    不错。

  12. 黑白的蘑菇 2015-7-11 · 13:52

    看这博客的主题直流口水,张教主,你分享了没有

    • avatar
      Jager 2015-7-11 · 14:40

      付费主题

      • 黑白的蘑菇 2015-7-11 · 14:41

        how much 必须有中文?

        • avatar
          Jager 2015-7-11 · 15:22

          百度搜begin主题。

  13. 大大 2015-7-29 · 18:27

    apache服务器怎么配置啊

  14. lock 2015-8-17 · 17:37

    感谢,最近想到这个但是不会写nginx规则。就看到这篇博文了。
    修改规则以后360CDN就可以正常缓存了,百度网站加速可以在没修改规则前用自定义规则强制缓存也不错。

    • lock 2015-8-28 · 19:51

      用博主的这个测试了下,貌似没效果。。。这是为什么 :sad:

    • Qa 2017-1-7 · 22:02

      懂了,因为我是外链的图片。
      下面对外链可用。

      set $url	'';
      set $url	$arg_url;
      rewrite ^/thumb/w(\d*)_h(\d*)/$ /timthumb.php?src=$arg_url&amp;w=$1&amp;h=$2&amp;zc=1&amp;q=85&amp;ct=1 last;
      
  15. 悟空 2017-5-5 · 9:25

    哈哈。昨晚灵光一闪,终于把这个问题解决了。 :grin:

  16. 悟空 2017-5-6 · 11:09

    Jager兄,发现一个问题:
    修改了缩略图的URL形式,然后重写回timthumb那个形式后。
    使用zhang.ge/*/xxx.jpg?w=xxx&h=xxx的方式访问是可以正常剪裁的。
    然后使用ob_start将URL中的zhang.ge替换为res.zgboke.com后
    URL就变成了res.zgboke.com/*/xxx.jpg?w=xxx&h=xxx,就出现了一个问题,图片不会被剪裁成指定大小,这样的话就会按整张图片进行缩放,缩略图就会出现不同的高度。具体请看截图:
    https://sunxyu.cn/image/zg.png

    • avatar
      Jager 2017-5-7 · 22:17

      之前发现了,主要没时间研究解决

      • 悟空 2017-5-10 · 10:26

        恭喜解决问题!本文评论还没有分页,刷新不了评论,我是在邮件通知中看到你回复的。

    • avatar
      Jager 2017-5-9 · 22:13

      已找到原因,nginx判断jpg的规则我写错了,写成了jgp,导致jpg的访问是直接请求到源图片文件的,没有裁剪。
      https://res.zgboke.com/wp-content/uploads/2016/01/cdn.jpg?w=200&h=151

      • avatar
        Jager 2017-5-10 · 15:48

        右下角点击绿色图标就能刷新本页评论。。。。。

  17. AFR 2017-6-15 · 22:44

    求问Jager大佬
    Nginx 缓存Timthumb的规则是什么,还是不太熟练,想不出来

  18. 老鬼 2017-9-13 · 19:37

    畅萌那个 timthumb.php?src= &h=x&w=x&zc=1 是带&的参数,博主的是带的?的,但是我只要给的带?的参数就报错了,我看博主的就是正常的,Jager是怎么解决的啊,求教。

    • 老鬼 2017-9-13 · 20:59

      解决了,是我那个 Nginx 配置顺序的问题 没有生效,重定向放在前面就生效了

  19. YF博客 2020-2-8 · 22:24

    你好,最后的代码貌似错了看下这样是不是正确的

    function content_thumbnail($content) {
            global $post;
            $pattern1 ="//i";
            $pattern2="//i";
            $pattern3 ="//i";
            $replacement = '';
            $replacement2 = 'post_title.'" tilte="'.$post-&gt;post_title.'"$7&gt;';
            $content = preg_replace($pattern2, $replacement, $content);
            $content = preg_replace($pattern3, $replacement, $content);
            $content = preg_replace($pattern1, $replacement2, $content);
            $content = preg_replace('//i', '', $content);
            return $content;
    }
    

    原来貌似是对的,不知道是不是因为换主题搞错了

    • avatar
      Jager 2020-2-8 · 23:31

      你的意思是我文章代码错了还是你的搞错了?你代码明显不行,是提交评论丢失内容了?提交代码评论就用代码高亮嘛。。。直接贴怎么看

      • YF博客 2020-2-9 · 19:41

        额...我记得贴代码的时候用了高亮的...而且丢了一部分内容...
        刚才又试了下,不知道是评论的代码高亮有问题还是我不会用...直接上图片吧

        首先,我是代码小白...直接用文章中的代码博客的文章内容会被吞掉,将return $content;放在在"}"上面就好了...

        • avatar
          Jager 2020-2-9 · 20:20

          return $content; 本来就在 } 之上吧。。。
          测试下代码高亮...

          add_filter ('the_content', 'content_thumbnail');
          function content_thumbnail($content) {
                  global $post;
                  $pattern1 ="/<img(.*?)src=('|\")(.*?).(bmp|gif|jpeg|jpg|png)('|\") alt=\"(.*?)\"(.*?)>/i"; $pattern2="/<img(.*?)src=('|\")(.*?)-300x(\d+?).(bmp|gif|jpeg|jpg|png)('|\")(.*?)>/i";
                  $pattern3 ="/<img(.*?)src=('|\")(.*?)-(\d+?)x300.(bmp|gif|jpeg|jpg|png)('|\")(.*?)>/i";
                  $replacement = '<img$1src=$2$3.$5$6$7>';
                  $replacement2 = '<img$1src=$2$3.$4?w=480$5 alt="'.$post->post_title.'" tilte="'.$post->post_title.'"$7>';
                  $content = preg_replace($pattern2, $replacement, $content);
                  $content = preg_replace($pattern3, $replacement, $content);
                  $content = preg_replace($pattern1, $replacement2, $content);
                  $content = preg_replace('/<img(.*?)width="(.*?)" height="(.*?)"(.*?)>/i', '<img$1$4>', $content);
          	return $content;
          }
          
          • YF博客 2020-2-9 · 20:23

            代码依然没高亮....上面的代码最后面多了一个}...

            • avatar
              Jager 2020-2-9 · 20:53

              修复了,多谢反馈。

          • YF博客 2020-2-9 · 20:25

            代码依然没高亮.....文章内代码最后面多了一个}。。。