Tag Archives: images

304 Not Modified Header and PHP

This is a nice little snipet that I use when serving dynamic images so the client will cache them properly. It uses a 304 Not Modified header to tell the client to not re-download the file. This mostly saves on TCP overhead however a connection must still be made to the server. I’m sure that somewhere out there is a header to make it so the client won’t even send the request in the first place see edit.

$info = $result->fetch_assoc();

// They have the current version
if (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == strtotime($info['updated'])) {
    header('Last-Modified: '.gmdate("D, d M Y H:i:s", strtotime($info['updated'])) . " GMT", true, 304);

// Sent them the file
} else {

    // Headers
    header("Content-type: image/jpeg");
    header("Last-Modified: " . gmdate("D, d M Y H:i:s", strtotime($info['updated'])) . " GMT");
    header("Expires: " . gmdate("D, d M Y H:i:s", strtotime(time() + 3600) . " GMT"); # 1h
    header("Cache-Control: public, maxage=3600"); # 1h
    header("Content-Length: ".strlen($info['image'])); 

    echo $info['image'];

The only issue with this code is 99% of the server side work is alredy done. If it isn’t a mission critical image you can do this at the top of the file instead to save a lot of back end time.

    header('Last-Modified: '.gmdate("D, d M Y H:i:s", strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])) . " GMT", true, 304);

Edit: Changing Cache-Control to public will make the browser just send a hello packet and not wait for a reply before showing the photo.