开发者

Dynamic resizing images cache

I use simple PHP code (zend framework) to resize jpg images on the fly.

Problem is I always end up with HTTP 200 status, instead having 304 and allow browsers to cache images.

I cant get apache headers, function_exists('apache_request_headers') is false, and in server variable I have only

 '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',

I'm sending

    $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');
  $开发者_StackOverflow社区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);

and I expected HTTP_IF_MODIFIED_SINCE or sth similar in server variable so I can do

  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);   
  }

Any idea?


The Last-Modified and If-Modified-Since values are not to be compared for equality. They both represent times. And if the Last-Modified time is greater than the If-Modified-Since time (so last modification took time after If-Modified-Since), the condition is fulfilled and 304 should be sent.

So you need to parse the If-Modified-Since value (try strtotime) and compare the values if the Last-Modified time is greater than the If-Modified-Since time:

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


Fixed with

$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);
    }

thanks to http://dustint.com/archives/25

When I added

$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 header in the request appeared, which helped me to match it against etag.

@Gumbo Oh, I understand it well :)

Thanks everyone who tried to help.


This Code snipped might help, it always worked for me, trying to integrate Cache Control into dynamically generated images in Zend Framework:

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;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜