How to Enable Client-Side Caching of Resized Images

About a month ago, I wrote a tutorial on dynamically resizing images in PHP. Despite my best intentions, I never found the time to go back and rewrite the script to include server-side caching of the images created.

However, one reader asked if it was possible to enable a client-side cache of a dynamically resized image. It surely is, and it’s very simple.

Dynamic Image Resizing: Revisited

If you’ve got no clue how to resize an image in PHP, then you ought to go back and re-read the original article. For the rest of you, here’s a quick refresher on what happens.

Our script takes a filename as a $_GET parameter. If the file exists, the script loads it in as an image resource. Using the GD library, we create a new image resource that is the proper size.

Finally, we use a content-type header to tell the browser to interpret the data as an image and we output the image data. Like this…

header("content-type: image/png");
imagepng($dst_img);

Enabling a Client Side Cache

In order to enable a client-side cache, all we need to do is add an extra header to the mix.

There is a set of headers in HTTP to handle this sort of need - Cache-Control. You can use this to enable caching, disable caching, and set some restrictions on what can be cached for how long.

The option we’re most interested in is max-age=[seconds]. This response header is sent along with the data to tell the browser that it can re-use a cached copy as long as it is no older than the specified age.

To enable this with PHP, add another header() call before the imagepng() call, and set a Cache-Control header with an appropriate max-age. Like so…

header("Cache-Control: max-age=3600");
header("content-type: image/png");
imagepng($dst_img);

Keep Request Queries Consistent

With this system, you could set a pretty long max-age for the cache. Assuming that the original image never changes, the user could cache a resized copy for months and your script would be happy.

However, you need to keep your query strings consistent for this to work. Since your request includes a query string, that full string is included in the location that is cached.

According to your browser, it’s not the image that is cached, it’s the location…

http://www.earn-web-cash.com/scripts/resize-image.php?image=http://www.earn-web-cash.com/wp-content/uploads/2008/01/dzone-screenshot.png

If you were to change the query string in any way - leaving out the www, for example - the browser will think it is fetching a new resource and it won’t consult the cache.

This is especially important if you include size parameters in the query string to dynamically choose the new size. You would need to be careful to keep the parameters in the same order every time for the cache to work properly.


Bookmark and Share:
These icons link to social bookmarking sites where readers can share and discover new web pages.

  • Digg
  • Furl
  • del.icio.us
  • StumbleUpon
  • MisterWong
  • DZone
  • Technorati

Tags: , , ,

10 Comments to “How to Enable Client-Side Caching of Resized Images”

  1. Rich said this on

    Works like a charm!

    Works in every browser (FF, IE, Safari, Opera..etc)

  2. Pat said this on

    Hey, cheers for the tute.

    I couldnt seem to get it to cache still, would calling the script through htaccess rewrite make any difference?

    ie http://www.domain.com/image/4.jpg

    Pat

  3. Pat said this on

    ok, I moved the cache control under the content-type:
    header(’Content-type: image/jpeg’);
    header(’Cache-Control: max-age=3600′);

    and now the reponse header is saying 3600 instead of ‘ no-store, no-cache, must-revalidate, post-check=0, pre-check=0′

    however I am still getting a passed expiry date.
    as in the following reponse headers:

    Date Mon, 10 Mar 2008 11:10:17 GMT
    Server Apache/1.3.39 (Unix) mod_auth_passthrough/1.8 mod_log_bytes/1.2 mod_bwlimited/1.4 mod_jk/1.2.14 mod_ssl/2.8.30 OpenSSL/0.9.7a PHP-CGI/0.1b
    Cache-Control max-age=3600
    Expires Thu, 19 Nov 1981 08:52:00 GMT
    Pragma no-cache
    X-Powered-By PHP/5.2.1
    Keep-Alive timeout=15, max=66
    Connection Keep-Alive
    Transfer-Encoding chunked
    Content-Type image/jpeg

    any idea why the expiry date would be in the past, the server time is correct
    Pat

  4. NL said this on

    Apaches default behavour is to disable caching as much as possible. That is why default headers are applied.

    You should be able to do:

    But some servers override the expire-header anyway :(

  5. NL said this on

    Apaches default behavour is to disable caching as much as possible. That is why default headers are applied.

    You should be able to do:

    – start of code –
    // Expire in 1 day
    $oDate = mktime(date(’H'), date(’i'), date(’s’), date(’m'), date(’d') + 1, date(’Y'));
    header(’Expires: ‘ . date(’D, d M Y H:i:s’, $oDate) . ‘ GMT’);
    – end of code –

    But some servers override the expire-header anyway :(

  6. suleiman said this on

    is there a way to set expire headers for images that are not hosted on your server?

  7. Quinta said this on

    Great work.

  8. Newblown said this on

    It’s so simple !

  9. John639 said this on

    Very nice site! cheap cialis http://opeaixy.com/qsqaxa/4.html

  10. Enable Client Side Caching for Resized Images - Tutorial Collection said this on

    […] View Tutorial No Comment var addthis_pub=”izwan00″; BOOKMARK This entry was posted on Friday, June 5th, 2009 at 8:19 am and is filed under Php Tutorials. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site. […]

Leave a Reply