Random writings on running, software & product development, business and anything else

PHP image output and browser caching

Recently I was involved in a project that returned graphic thumbnails in response to a remote php script call. One of the optimisations done was to have browser caching of returned images to save on our bandwidth. I will share the code we used to do this.

The code is pretty simple, and borrows heavily from code pasted by mandor at mandor dot net for the PHP header function. We generalised it for different graphic file types and a second function so it works when PHP is an Apache module or cgi.

The first function displayGraphicFile is to return a graphic file. The function does assume the file exists.

// Return the requested graphic file to the browser
// or a 304 code to use the cached browser copy
function displayGraphicFile ($graphicFileName, $fileType='jpeg') {
  $fileModTime = filemtime($graphicFileName);
  // Getting headers sent by the client.
  $headers = getRequestHeaders();
  // Checking if the client is validating his cache and if it is current.
  if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == $fileModTime)) {

    // Client's cache IS current, so we just respond '304 Not Modified'.
    header('Last-Modified: '.gmdate('D, d M Y H:i:s', $fileModTime).' GMT', true, 304);
  } else {
    // Image not cached or cache outdated, we respond '200 OK' and output the image.
    header('Last-Modified: '.gmdate('D, d M Y H:i:s', $fileModTime).' GMT', true, 200);
    header('Content-type: image/'.$fileType);
    header('Content-transfer-encoding: binary');
    header('Content-length: '.filesize($graphicFileName));
    readfile($graphicFileName);
  }
}

The second function to get the header request details. We specifically require the ‘If-Modified-Since’ header.

// return the browser request header
// use built in apache ftn when PHP built as module,
// or query $_SERVER when cgi
function getRequestHeaders() {
  if (function_exists("apache_request_headers")) {
    if($headers = apache_request_headers()) {
      return $headers;

    }
  }
  $headers = array();
  // Grab the IF_MODIFIED_SINCE header
  if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
    $headers['If-Modified-Since'] = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
  }
  return $headers;
}

2 Comments

  1. Doug

    Thanks man. You really saved me and my time.

  2. Darius J.

    Nice! Many thanks!

© 2024 Ernie Leseberg

Theme by Anders NorenUp ↑