【问题标题】:Create resized image cache but prevent abuse创建调整大小的图像缓存但防止滥用
【发布时间】:2012-06-25 12:17:40
【问题描述】:

好的,我知道我想如何提供和缓存我的图像。 我不知道这是否是正确的做法,但如果是,我想知道如何防止滥用。

情况:

index.php

<img src="images/cache/200x150-picture_001.jpg" />

图像/缓存/.htaccess

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ images/image.php?f=$1 [L]

上面检查图片是否存在,如果不存在则重写为image.php

image.php 伪代码

从文件名中获取高度和宽度

调整图片大小并保存到缓存文件夹

使用 content-type 和 readfile 提供图像。

通过这种方式,我试图通过 readfile 减少 HTTP 请求和 PHP 负载。 如果存在则浏览器获取图像/jpeg,如果不存在则生成。

最终所有图片都将被缓存并以正确的高度和宽度提供服务,这样浏览器就不会下载过大的图片。

唯一的问题..如果您将图片网址更改为不同的尺寸,您可以填满服务器。

我做得对吗,正确的做法是什么。有没有机会阻止这种情况发生?

我知道缓存的整个概念已经被提炼了一百万次,请赐教。

【问题讨论】:

    标签: php image .htaccess caching


    【解决方案1】:

    不确定我是否回答得还不算太晚,但你为什么不简单地使用SLIR (Smart Lencioni Image Resizer) 呢?它可以做任何您需要的事情(包括缓存和缓存管理),因此您只需将其放入并使用。

    【讨论】:

      【解决方案2】:

      一些方法:

      • 维护一个允许分辨率的数组,并检查请求的分辨率是否在该数组中。缺点:不编辑数组就无法快速添加分辨率。

      • 如果这是在 CMS 上下文中:只允许经过身份验证的用户创建 图像(尚未在缓存中);否则拒绝该请求。当经过身份验证的用户在 CMS 中添加图像时,他们会预览它,然后生成调整大小的图像。缺点:不太容易实现。

      【讨论】:

      • 考虑到这种特殊情况适用于网上商店,允许的分辨率数组听起来还不错。
      • CMS 上下文是可能的,我通常将 CKeditor 用于我的 CMS,并且能够编辑代码使其指向我想要的文件。
      • 我决定接受这个答案,因为我觉得这些解决方案在当前情况下最容易应用。谢谢。
      【解决方案3】:

      缓存显然是一个重要的问题 - 您的解决方案似乎合理,但确实容易受到有意和无意的拒绝服务攻击。它也没有解决图像更改时会发生什么 - 如何从缓存中删除所有调整大小的图像?它没有设置缓存标头以允许“下游”缓存。它没有处理同时刷新整个缓存的风险,需要在 HTTP 请求的上下文中重新生成所有图像,这可能是主要的性能消耗..

      您是否查看过诸如Apache's caching module 之类的“现成”解决方案?

      【讨论】:

      • 没错,重新生成缓存是第一次访问时的主要性能损失。对于这种特殊情况,网站在 IIS 上运行,我无权安装模块。然而,对于我的其他项目,我肯定会考虑这一点。谢谢。
      【解决方案4】:

      我只是这样做:

      <img src="/thumbnail.php?thumb=mybigpicture.ext" ... />
      

      这就是我的做法。请注意,无论图像是宽还是高,此实现都会缩放图像,并且与大多数 PHP 尝试不同,它在缩放方面做得不错。

      <?php
      
      function thumb_image($request = "") {
        $cfgthumb['folder'] = "/images/cache";
        $cfgthumb['height'] = 150;
        $cfgthumb['width'] = 200;
        $cfgthumb['error'] = "/images/error.jpg";
        $cfgthumb['default'] = "/images/notfound.jpg";
      
        $thumb = $cfgthumb['folder'] . "/" . md5($request);
        header("Content-Type: image/jpeg");
        if (is_readable($thumb)) echo file_get_contents($thumb);
        elseif (is_readable($request)) {
          $extension = strtolower(end(explode(".", $request)));
          switch ($extension) {
          case "gif":
            $simage = imagecreatefromgif($request);
            break;
          case "jpeg":
          case "jpg":
            $simage = imagecreatefromjpeg($request);
            break;
          case "png":
            $simage = imagecreatefrompng($request);
            break;
          }
          if ($simage) {
            $simage_width = imagesx($simage);
            $simage_height = imagesy($simage);
            if (($simage_width > $cfgthumb['width']) || ($simage_height > $cfgthumb['height'])) {
              if ($simage_width > $simage_height) {
                $dimage_width = $cfgthumb['width'];
                $dimage_height = floor($simage_height * ($cfgthumb['width'] / $simage_width));
              } else {
                $dimage_width = floor($simage_width * ($cfgthumb['height'] / $simage_height));
                $dimage_height = $cfgthumb['height'];
              }
            } else {
              $dimage_width = $simage_width;
              $dimage_height = $simage_height;
            }
            $dimage = imagecreatetruecolor($dimage_width, $dimage_height);
            imagegammacorrect($simage, 2.2, 1.0);
            imagecopyresampled($dimage, $simage, 0, 0, 0, 0, $dimage_width, $dimage_height, $simage_width, $simage_height);
            imagegammacorrect($dimage, 1.0, 2.2);
            imagejpeg($dimage, $thumb, 100);
            imagejpeg($dimage, NULL, 100);
            imagedestroy($simage);
            imagedestroy($dimage);
          } else echo file_get_contents($cfgthumb['error']);
        } else echo file_get_contents($cfgthumb['default']);
      }
      
      ?>
      

      【讨论】:

      • 我已经有了这段代码,除了我的代码处理动态尺寸外,我这样做的方式是减少服务器负载,让浏览器获取图像文件而不是:服务器然后浏览器。问题是我想要一种方法来防止人们填满我的服务器。这可以通过@Pekka 允许的维度数组来实现。
      • 很抱歉,如果这并不能真正解决您的具体问题。我更喜欢让 PHP 处理整个过程,而不是使用 mod_rewrite 或类似的方法(即,这可能允许访问磁盘上的静态文件),原因有两个:首先,您只需要处理源图像文件和缩略图“照顾好自己”,其次,您不需要一次生成一大堆缩略图,因为它们是按需生成的。
      • 就像我说的,让 PHP 为文件提供服务会尽可能少地增加负载。直接将访问者指向图像文件然后指向提供图像的 php 文件会更快。此外,按照我解释的方式,一切都将按需生成。 “您只需要打扰源图像文件”,您是什么意思?我的方法也是这样吗?我们的方法之间几乎没有任何区别,除了我通过使用 mod_rewrite 取出 php 提供文件的步骤,并且只在文件不存在且必须生成时使用 php 提供文件,之后的时间将采用生成的图像。
      • 你是对的。我的方法的唯一优点是您不会以 .htaccess 和/或 httpd.conf + apachectl restart 结束(顺便说一下,如果您担心性能,应该这样做),这与使用 apache(缓存和)服务静态图像(如果存在)相比,优势明显要小。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-14
      • 2018-10-11
      • 1970-01-01
      • 2011-01-24
      • 2012-08-09
      • 1970-01-01
      • 2011-11-07
      相关资源
      最近更新 更多