Sven van Zoelen
Sven van Zoelen

Reputation: 7229

How to cache script image

I want to implement an script that generates an thumbnail on the requested file (image). Here is a simple list of actions to understand the working of the script:

This works perfect, but the problem is that the images are not cached by the browser. I'm not that familiar with caching. I thought by returning 304 Not modified would trigger the browser to get the image from the cache but it hangs in pending state.

Does someone know how to cache these images?

This is the show part of my script:

private function _show_image($file_path, $filename, $new = FALSE) {
        $this->load->helper('file');

        if($new) { 
            header($_SERVER['SERVER_PROTOCOL'] . ' 200 OK');
        } else {
            //header('HTTP/1.1 304 Not Modified');
            header($_SERVER['SERVER_PROTOCOL'] . ' 304 Not Modified');  
        }

        header('Cache-Control: public'); // needed for i.e.
        header('Content-type: ' . get_mime_by_extension($file_path));
        header('Content-Transfer-Encoding: Binary');
        header('Content-Length:' . filesize($file_path));
        //header('Content-Disposition: attachment; filename=' . $filename);
        header('Content-Disposition: inline; filename=' . $filename);
        readfile($file_path);
        exit(); 
    }

Update

I updated the code so that it first checks if the $_SERVER['HTTP_IF_MODIFIED_SINCE'] is set, if so do all the check stuff. But the thing is that the browser is not sending that header ever..

Here are the send and received headers when accessing the file.

Request

Accept:*/*
Accept-Encoding:identity;q=1, *;q=0
Accept-Language:nl-NL,nl;q=0.8,en-US;q=0.6,en;q=0.4
Connection:keep-alive
Cookie:PHPSESSID=heiog0hdasg181l45cfbm7u353; __jwpusr=264f6c61-3752-4682-a61b-e02b822c7815
Host:domain.local
Range:bytes=0-
Referer:http://domain.local/test
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36

Response

Cache-Control:public
Connection:Keep-Alive
Content-Description:File Transfer
Content-disposition:inline
Content-Length:24103476
Content-Transfer-Encoding:binary
Content-Type:video/mp4
Date:Thu, 30 May 2013 14:07:02 GMT
Expires:0
Keep-Alive:timeout=5, max=98
Last-Modified:Wed, 29 May 2013 09:03:30 GMT
Server:Apache/2.2.22 (Win32) PHP/5.3.13
X-Frame-Options:SAMEORIGIN
X-Powered-By:PHP/5.3.13
X-XSS-Protection:1; mode=block 

Upvotes: 0

Views: 171

Answers (3)

Martin
Martin

Reputation: 6015

If you are using Apache, you might be better off adding mod_rewrite. You could create a rewrite rule that redirects the request to PHP only if the requested image does not exist.

.htaccess file in your thumbnails directory:

RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule .* /thumbnailer.php

thumbnailer.php needs to then check $_SERVER['REDIRECT_URL'] (or some similar variable, check phpinfo) to see which file needs to be generated.

Upvotes: 2

Erik Nedwidek
Erik Nedwidek

Reputation: 6184

You may only send a 304 "Not Modified" IF the client sent you a If-Modified-Since header such as:

If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT

Or a If-None-Match:

If-None-Match: "737060cd8c284d8af7ad3082f209582d"

You can't know if the image is still in the browser's cache or if it has been cleaned out. The correct action is to return the image when you create the thumbnail. If the thumbnail exists, check the If-Modified-Since header (this is the browser indicating that it currently has the file in its cache) and return a 304 Not Modified if the file has not changed. Otherwise return the file since it won't be in the browser's cache.

The If-None-Match system uses eTags and you're just better off avoiding those if you don't need to deal with them.

Upvotes: 2

MarZab
MarZab

Reputation: 2623

My first tip would be, if you can, to leave the caching to Apache itself. It knows best how to send the headers and respond to requests for cache.

If you really want to do this yourself, you need to figure out when a browser requests the image or just checks if there was a change (If-Modified-Since).

You did not set a expires nor max age, so it might not have cached the image at all.

Expires Mon, 16 Oct 2012 11:07:06 GMT
Cache-Control   public, max-age=120

And when it gave a new request (without a If-Modified-Since), you just sent back a 304 that it did not expect.

Upvotes: 1

Related Questions