Caching remote images locally with mod rewrite and PHP
Sometimes you need to load images from a remote server. In my case it was a customer site that used an external image service. The only problem was that the image service was a bit unreliable and slow - which made the customer’s site look slow.
We decided to make a local cached copy of the images, and the solution was simple enough to share here. The website was running on Apache and we took advantage of the mod_rewrite module by placing the following in our .htaccess file.
RewriteEngine On
# Images
RewriteCond %{REQUEST_URI} ^/images/
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule (.*) /images/cache.php?querystring=$1 [L]
This means that all requests to /images/ that does not match a real file hits our images/cache.php with the image request path as the querystring.
<?php
# Ok, the file does not exist on our server. Get it from the remote server
# http://example.com/pictures/$image_path
$image_path = $_GET['querystring'];
# You may want to do some sanity checking here, depending on which file names
# you are allowing.
$url = "http://example.com/pictures/$image_path";
# Check to see if we can load the URL at all.
$data = @file_get_contents($url);
if($data)
{
# Permission to write to server is required.
file_put_contents("$image_path", $data);
# Redirect the user to the remote server this time.
# Next time she will get the cached image.
header("Location: $url");
} else {
# Did not find the image on remote server. Send user to our missing image.
header("Location: http://example.com/images/missing.png");
}
?>
In our production code we have some more security measures to see that the filename is a valid path, matches some given filenames and does not contain strange characters. But this will give you a nod in the right direction if you need to build something similar.