Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to cache resized images using PHP and MySQL

What would be the best practice way to handle the caching of images using PHP.

The filename is currently stored in a MySQL database which is renamed to a GUID on upload, along with the original filename and alt tag.

When the image is put into the HTML pages it is done so using a url such as '/images/get/200x200/{guid}.jpg which is rewritten to a php script. This allows my designers to specify (roughly - the source image maybe smaller) the file size.

The php script then creates a hash of the size (200x200 in the url) and the GUID filename and if the file has been generated before (file with the name of the hash exists in TMP directory) sends the file from the application TMP directory. If the hashed filename does not exist, then it is created, written to disk and served up in the same manner,

Is this efficient as it could be? (It also supports watermarking the images and the watermarking settings are stored in the hash as well, but thats out of scope for this.)

like image 949
Chris Hawes Avatar asked Sep 26 '08 17:09

Chris Hawes


1 Answers

I would do it in a different manner.

Problems: 1. Having PHP serve the files out is less efficient than it could be. 2. PHP has to check the existence of files every time an image is requested 3. Apache is far better at this than PHP will ever be.

There are a few solutions here.

You can use mod_rewrite on Apache. It's possible to use mod_rewrite to test to see if a file exists, and if so, serve that file instead. This bypasses PHP entirely, and makes things far faster. The real way to do this, though, would be to generate a specific URL schema that should always exist, and then redirect to PHP if not.

For example:

RewriteCond %{REQUEST_URI} ^/images/cached/
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f
RewriteRule (.*) /images/generate.php?$1 [L]

So if a client requests /images/cached/<something> and that file doesn't exist already, Apache will redirect the request to /images/generate.php?/images/cached/<something>. This script can then generate the image, write it to the cache, and then send it to the client. In the future, the PHP script is never called except for new images.

Use caching. As another poster said, use things like mod_expires, Last-Modified headers, etc. to respond to conditional GET requests. If the client doesn't have to re-request images, page loads will speed dramatically, and load on the server will decrease.

For cases where you do have to send an image from PHP, you can use mod_xsendfile to do it with less overhead. See the excellent blog post from Arnold Daniels on the issue, but note that his example is for downloads. To serve images inline, take out the Content-Disposition header (the third header() call).

Hope this helps - more after my migraine clears up.

like image 74
Tikeb Avatar answered Oct 13 '22 18:10

Tikeb