File Downloads with php in Internet Explorer

For a web project with restricted access I wrote a script to download files via php. Basically I use rewrite rules to send the user to the php script, the script checks if the session is ok and sends the download (prepended by several headers) if the user has the proper permissions and the file is located in a directory that’s whitelisted.
Here’s the RewriteRule:

  1. RewriteRule ^/(downloads/.*) https://www.server.org/download.php?f=$1 [L,R,NC]

It worked fine except … Internet Explorer. In some cases, IE6 refused to save the file correctly. It just saved it with the name download.php and “unknown type”. Regardless of the type I sent along with Content-type and the name I sent with Content-Disposition.

I found lots of different infos on which headers are to be sent exactly in order to make IE work. This one looked good to me (without deeper knowledge on how IE6 interprets http headers:

  1. /* First check the session if the user is valid, if he is allowed to download $file and set $type, $file, $size. */
  2. if (strstr($_SERVER[‘HTTP_USER_AGENT’],"MSIE")) {
  3.   header("Pragma: public");
  4.   header("Expires: 0");
  5.   header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
  6.   header("Content-type: $type");
  7.   header("Content-Length: $size");
  8.   header("Content-Disposition attachment; filename=$file");
  9.   header("Content-Transfer-Encoding: binary");
  10. } else {
  11.   header(‘Cache-Control: maxage=3600′); //Adjust maxage appropriately
  12.   header(‘Pragma: public’);
  13.   header("Content-type: $type");
  14.   header("Content-Disposition: attachment; filename=\"$file\"");
  15.   header("Content-length: $size");
  16. }
  17. readfile ($file);

However — it didn’t work. Until I found a msdn article about type-guessing. Internet Explorer 6 tries to guess the file type by using the file name. Even if you send a valid Content-type header.
The really bad thing is that IE doesn’t use the filename sent along with Content-Disposition but the file name in the url.

So the actual fix was changeing the RewriteRule (which wasn’t optimal anyway):

  1. RewriteRule ^/(downloads/.*) https://www.server.org/download.php?f=$1 [L,NC]

If you skip the R (for Redirect) the URL doesn’t change so the browser ‘sees’ the actual filename instead of download.php. IE6 can guess the type and everyone is happy (I hope).

Tags: , ,

Leave a Reply

Page optimized by WP Minify WordPress Plugin