【问题标题】:Dynamic resizing images cache动态调整大小图像缓存
【发布时间】:2011-01-24 10:15:43
【问题描述】:

我使用简单的 PHP 代码(zend 框架)即时调整 jpg 图像的大小。

问题是我总是以 HTTP 200 状态结束,而不是 304 并允许浏览器缓存图像。

我无法获取 apache 标头,function_exists('apache_request_headers') 是假的,并且在服务器变量中我只有

 'HTTP_ACCEPT' => 'image/png,image/*;q=0.8,*/*;q=0.5',
  'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7',
  'HTTP_ACCEPT_ENCODING' => 'gzip,deflate',
  'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5',
  'HTTP_CACHE_CONTROL' => 'max-age=0',
  'HTTP_CONNECTION' => 'keep-alive',
  'HTTP_COOKIE' => '***',
  'HTTP_HOST' => 'automobi.li',
  'HTTP_KEEP_ALIVE' => '300',
  'HTTP_REFERER' => 'http://automobi.li/oglas/Opel+Astra/2',
  'HTTP_USER_AGENT' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.8) Gecko/20100202 Firefox/3.5.8 FirePHP/0.4',

我正在发送

    $lastModified = filemtime($path);
  $etag = md5_file($path);

  $this->getResponse()->setHeader('Content-type', 'image/jpeg');
  $this->getResponse()->setHeader('Cache-Control', 'public');
  $this->getResponse()->setHeader('Last-Modified', gmdate('D, d M Y H:i:s', $lastModified) . ' GMT');
  $this->getResponse()->setHeader('Cache-Control', 'max-age=86400, must-revalidate');
  $this->getResponse()->setHeader('Expires', gmdate('D, d M Y H:i:s', time() + 86400 ) . ' GMT');
  $this->getResponse()->setHeader('ETag', $etag);

我希望 HTTP_IF_MODIFIED_SINCE 或类似的服务器变量,所以我可以这样做

  if ($this->getRequest()->getHeader('IF_MODIFIED_SINCE') == $lastModified) {
$this->getResponse()->setHttpResponseCode(304);

  } else {
   $w = (int) $this->_getParam('w');
   $h = (int) $this->_getParam('h');
   $image->resize($path, $w, $h);   
  }

有什么想法吗?

【问题讨论】:

    标签: php http image resize


    【解决方案1】:

    Last-ModifiedIf-Modified-Since 值不会进行相等性比较。它们都代表时间。并且如果 Last-Modified 时间大于 If-Modified-Since 时间(所以最后一次修改花费了 If-Modified-Since 之后的时间),条件满足,应该发送304。

    所以你需要解析 If-Modified-Since 值(尝试strtotime),如果 Last-Modified 时间大于If-Modified-Since 时间:

    if ($lastModified > strtotime($this->getRequest()->getHeader('IF_MODIFIED_SINCE'))) {
        $this->getResponse()->setHttpResponseCode(304);
    }
    

    【讨论】:

    • 谢谢,我知道,我只是写得很快,没有在意细节。如果您查看 $_SERVER 变量,您会发现 IF_MODIFIED_SINCE 没有设置,正如我已经写过的,apache_request_headers 没有定义函数,这是主要问题,我没有这个数据!所以我正在寻找一个解决方案,如何确定它。
    • 如果$_SERVER['IF_MODIFIED_SINCE']没有设置,那么客户端没有发送If-Modified-Since头域,你不能用它来判断客户端的表示是否是还是新鲜的。
    • 好的,但是用什么代替呢?必须有某种方法来确定客户端缓存。
    • @auto:你就是做不到。缺少该信息的原因可能有多种。例如,因为这是该资源的第一个请求,或者客户端不支持缓存。
    • @Gumbo 我不同意。 1. 即使这不是第一个请求,它也会发生。 2. 客户端支持缓存,因为它会缓存静态资源(其他图片、js和css)。
    【解决方案2】:

    固定为

    $this->getResponse()->setHeader('Content-type', 'image/jpeg');
        $this->getResponse()->setHeader('Expires', '', true);
        $this->getResponse()->setHeader('Cache-Control', 'public', true);
        $this->getResponse()->setHeader('Cache-Control', 'max-age=3800');
        $this->getResponse()->setHeader('Pragma', '', true);
        $this->getResponse()->setHeader('ETag', $etag);
    
        if ($etag == $this->getRequest()->getHeader('If-None-Match')) {
            $this->getResponse()->setHttpResponseCode(304);
        } else {
            $w = (int) $this->_getParam('w');
            $h = (int) $this->_getParam('h');
            $image->resize($path, $w, $h);
        }
    

    感谢http://dustint.com/archives/25

    当我添加时

    $this->getResponse()->setHeader('Expires', '', true);
        $this->getResponse()->setHeader('Cache-Control', 'public', true);
        $this->getResponse()->setHeader('Cache-Control', 'max-age=3800');
        $this->getResponse()->setHeader('Pragma', '', true);
    

    出现了请求中的 If-None-Match 标头,这有助于我将其与 etag 进行匹配。

    @Gumbo 哦,我明白了:)

    感谢所有试图提供帮助的人。

    【讨论】:

      【解决方案3】:

      这段代码可能会有所帮助,它总是对我有用,试图将缓存控制集成到 Zend 框架中动态生成的图像中:

      if ($mod_since = $this->getRequest()->getHeader('If-Modified-Since')) {
      
          $request_modified = explode(';', $mod_since);
          $request_modified = strtotime($request_modified[ 0 ]);
      
      }
      if ($this->getFiletime($path, $filename) > 0 && $this->getFiletime($path, $filename) <= $request_modified) {
      
          // Image has not changed since last call, force Browser to reload from cache.
          header('HTTP/1.1 304 Not Modified');
          exit();
      
      } else {
      
          // Image has changed or browser has no cache
          $mimetype = $this->getMIMEType($path, $filename);
          $format = substr(strstr($mimetype, "/"), 1);
          $this->getResponse()->setHeader('Content-type', $mimetype);
          $expires = 60 * 60 * 24 * 3;
          $exp_gmt = gmdate("D, d M Y H:i:s", time() + $expires) . " GMT";
          $mod_gmt = gmdate("D, d M Y H:i:s", $this->getFiletime($path, $filename)) . " GMT";
      
          $imagedata = $this->_processor->processImage($path, $filename, $w, $h, $crop, $format);
      
          // Send Headers for Browser Caching Control
          $this->getResponse()->setHeader('Expires', $exp_gmt, true);
          $this->getResponse()->setHeader('Last-Modified', $mod_gmt, true);
          $this->getResponse()->setHeader('Cache-Control', 'public, max-age=' . $expires, true);
          $this->getResponse()->setHeader('Pragma', '!invalid', true);
          $this->getResponse()->setHeader('Content-Length', strlen($imagedata), true);
          $this->getResponse()->setHeader('ETag', md5($imagedata), true);
      
          // Save image in Zend Framework's server side Cache or get it from there
          $cache_id = str_replace(".", '', $path . "_" . $filename . "_" . $w . "_" . $h . "_" . $crop . "_" . $format);
      
          if (!$result = $this->_cache->load($cache_id)) {
              $result = $imagedata;
              $this->_cache->save($result, $cache_id, array('image', $path . '_' . str_replace(".", '', $filename)));
          }
          echo $result;
      }
      

      【讨论】:

        猜你喜欢
        • 2011-02-18
        • 2013-04-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-01-28
        • 2015-11-21
        • 1970-01-01
        相关资源
        最近更新 更多