tags:

views:

21

answers:

3

I have a PHP script that simply takes some data, separates it into tab delimited format, saves it as an .xls file, and then gives user a link to download it.

Works well most of the time, but some people are getting cached versions of the exported .xls file.

What I am thinking I need to do is instead of giving user a direct link to the .xls document, give them a link a PHP page something like this:

deliver_excel_doc.php?file=some_excel_file.xls&

then the deliver_excel_doc.php pulls in the data from the excel doc but does something with headers so the excel doc is not cached and then outputs as xls so the file will be downloaded (or rendered inside excel).

Any ideas on how I can do this (is this concept viable)?

+3  A: 

You could version your urls as you wrote, but instead of doing that, send the proper headers:

<?php
header("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // Date in the past
?>
erenon
+2  A: 

Just add a timestamp to the link getting the Excel File, e.g.

printf('<a href="file.xls?%d">Excel File</a>', time());

Because the timestamp is always different, their browser won't cache the file.

Gordon
On the other hand, this method doesn't help is a user bookmarks the download url. (If caching is a problem, this could happen)
erenon
True, the above cannot prevent caching in bookmarked links.
Gordon
OneNerd
+1  A: 

If the clients are caching the output of your PHP then you have a much bigger problem than you thought!

erenon is partially right about setting the caching instructions correctly, however if you serve it up with an expired cache date, then you'll find that Excel will often fail to open the document (if its accessed via MSIE). A better solution is to set an expiry time just a few seconds in the future, and ask proxies not to cache it:

if ($_SERVER['SERVER_PROTOCOL']=='HTTP/1.0') {
    header("Expires: " . date('r', time()+3));
} else {
    header("Cache-Control: max-age=3, private, must-revalidate");
}

While HTTP/1.1 will support the Expires header, for this to behave as expected, the client clock must be in sync with the server clock.

(note that date() throws warnings if you don't set the timezone)

C.

symcbean