yes i love technology

PHP: File Downloads HTTP Headers

May 16th, 2007 by Pete

In PHP you can provide file downloads by using a PHP page to “pass through” the file. Of course you could just link to the actual file, however this technique means your file can kept outside of your website root. Another advantage is you can integrate this system into a PHP based user/password system easily.

Now this technique is fairly straightforward, but you need to make sure you get the HTTP Headers correct for it to run smoothly. Here’s the code:

PHP:
  1. $file = "/path/to/file.txt";
  2. $file_extension = strtolower(substr(strrchr($basename,"."),1));
  3.  
  4. //This will set the Content-Type to the appropriate setting for the file
  5. switch ($file_extension)
  6. {
  7. case "htm":
  8. case "xhtml";
  9. case "txt";
  10. case "html": $ctype="text/html"; break;
  11. case "pdf": $ctype="application/pdf"; break;
  12. case "doc": $ctype="application/msword"; break;
  13. case "exe": $ctype="application/octet-stream"; break;
  14. case "zip": $ctype="application/zip"; break;
  15. case "xls": $ctype="application/vnd.ms-excel"; break;
  16. case "ppt": $ctype="application/vnd.ms-powerpoint"; break;
  17. case "gif": $ctype="image/gif"; break;
  18. case "png": $ctype="image/png"; break;
  19. case "jpeg":
  20. case "jpg": $ctype="image/jpeg"; break;
  21. case "mp3": $ctype="audio/mpeg"; break;
  22. case "wav": $ctype="audio/x-wav"; break;
  23. case "mpeg":
  24. case "mpg":
  25. case "mpe": $ctype="video/mpeg"; break;
  26. case "mov": $ctype="video/quicktime"; break;
  27. case "avi": $ctype="video/x-msvideo"; break;
  28. default: $ctype="application/force-download";
  29. }
  30.  
  31. //Begin writing headers
  32. header("Pragma: public");
  33. header("Expires: 0");
  34. header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
  35. header("Cache-Control: public");
  36. header("Content-Description: File Transfer");
  37. //Use the switch-generated Content-Type
  38. header("Content-Type: $ctype");
  39. header("Content-Length: ".filesize($file));
  40.  
  41. // regex stops download prompt for browser associated types
  42. if (!preg_match('/(htm|xhtml|txt|html|gif|png|jpeg|jpg)/', $file_extension, $matches))
  43. header("Content-Disposition: attachment; filename=\"".basename($filename)."\";" );
  44.  
  45. // output the file
  46. readfile("$file");
  47. exit();

I will be writing a follow up article in the future that shows how this technique can be improvement using Apache's mod-rewrite to provide cleaner URLs for file downloads.

Note: The regular expression on line 42 will make files normally associated with the browser (images, webpages, etc) open inside the browser. If you want to get the “open/save” download prompt for all types of files then comment out this line.

Note: Make sure you use: “Content-Type: image/jpeg” for JPGs, IE doesn’t seems to like “Content-Type: image/jpg”

# Pete Graham

Posted in Website Development, php, regular expressions, programming |

2 Responses

  1. Sculupencoupe Says:

    I’d prefer reading in my native language, because my knowledge of your languange is no so well. But it was interesting! Look for some my links:

  2. Niklas Moller Says:

    is this script open to hack attacks that try to download any file off the server directory?

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.