This is not a tutorial, just some source code that might help you out if you’re looking for hints.
The code below won’t run for you out of the box because you don’t have my framework, but here is a brief explanation of what it does:
If a browser requests a URI like /image/some-image-slug.jpg then “some-image-slug” is looked up and the product ID associated with it is used to reference the image files.
The URI path can include “full” or “thumb” before the slug, like /image/thumb/some-image-slug.jpg.
If the cached image doesn’t exist or is older than the original, then the full or thumb image is remade.
The file modification time of the cached image is used to manage the IF_MODIFIED_SINCE stuff…
My original lesson on IF_MODIFIED_SINCE was found here:
Caching Behavior of Web Browser (pdf)
This post was quite helpful:
If-Modified-Since HTTP Header – How to Use with PHP
This was also helpful:
Creating Thumbnails with PHP using the GD Library
define(“_SC_FRAME”, true);
$maxWidths = array(“full” => 300, “thumb” => 100);
require_once(“fw/fw.php”);
CONFIG::$debugEcho = false;
$parts = preg_split(‘///’, preg_replace(‘/.[a-z]+$/’, ”, $_SERVER[‘REQUEST_URI’]), 4, PREG_SPLIT_NO_EMPTY);
if (count($parts) >= 3) {
$size = $parts[count($parts) – 2];
if ($size == “image”)
$size = “full”;
elseif ($size != “full” && $size != “thumb”)
$size = null;
}
$slug = $parts[count($parts) – 1];
if (count($parts) < 3 || !$size) {
header(“Status: 400 Bad Request”);
echo “400 Bad Request”;
exit();
}
$prodId = DB::querySingleValue(“SELECT id FROM ” . DB::table(“prods”) . ” WHERE slug = ” . DB::esc($slug));
if (!$prodId) {
header(“Status: 404 Not Found”);
echo “404 Not Found: $slug”;
exit();
}
$filename = mapPath(“/sc/product-images/$size/$prodId.jpg”);
$original = mapPath(“/sc/product-images/original/$prodId.jpg”);
$originalExists = file_exists($original);
$filenameExists = file_exists($filename);
if ($originalExists && $filenameExists && filemtime($original) > filemtime($filename)) {
// To avoid a delay in the system read of the modification time…
// If you save over the same inode, the modification time seems to stick for a bit
// on the system I’m using. There’s probably a better way to do this.
unlink($filename);
$filenameExists = false;
}
if (!$filenameExists) {
if (!$originalExists) {
header(“Status: 404 Not Found”);
echo “404 Not Found: $slug (no original)”;
exit();
}
list($width, $height) = getimagesize($original);
if ($width <= $maxWidths[$size]) {
copy($original, $filename);
//debug_str(“copied”);
} else {
$modWidth = $maxWidths[$size];
$modHeight = $height * $modWidth / $width;
$tn = imagecreatetruecolor($modWidth, $modHeight);
$ext = pathinfo($original, PATHINFO_EXTENSION);
switch ($ext) {
case “jpg”:
$image = imagecreatefromjpeg($original);
break;
case “gif”:
$image = imagecreatefromgif($original);
break;
case “bmp”:
$image = imagecreatefromwbmp($original);
break;
case “png”:
$image = imagecreatefrompng($original);
break;
default:
header(“Status: 500 Error”);
echo “500 Unknown original file extension [$ext]”;
exit();
}
imagecopyresampled($tn, $image, 0, 0, 0, 0, $modWidth, $modHeight, $width, $height);
imagejpeg($tn, $filename);
//debug_str(“sampled”);
}
}
$lastModified = filemtime($filename);
if (array_key_exists(“HTTP_IF_MODIFIED_SINCE”, $_SERVER)) {
$if_modified_since = strtotime(preg_replace(‘/;.*$/’, ”, $_SERVER[“HTTP_IF_MODIFIED_SINCE”]));
//debug_str( date(“r”,$if_modified_since) . ” ” . date(“r”,$lastModified));
if ($lastModified <= $if_modified_since) {
header(“Status: 304 Not Modified”);
//debug_str(“not modified”);
exit();
}
}
header(‘Content-type: image/jpeg’);
header(‘Last-Modified: ‘ . gmdate(DATE_RFC1123, $lastModified));
readfile($filename);
//debug_str(“sent”);?>
Leave a Reply