How to force downloads with PHP the easy way

Posted in Development, Tutorials by Alex Stoia

Often, when you are creating a website, you might want your users to be able to download a file directly from a link and not having to educate the user like “Right-click and select ‘Save As…’ “-scenario
But as you might have noticed, the conventional way is not always working because of the different technologies (browsers,platforms,etc) used.  By conventional I mean:

href="music_file.mp3"

The solution to this problem, with php, is a ‘ header soup’ that will help you do this the right way.

Create a file, for ex. download.php, which will handle the download transactions, and insert the following code in it:

<?php header(“Pragma: public”);
header(“Expires: 0″);
header(“Cache-Control: must-revalidate, post-check=0, pre-check=0″);
header(“Cache-Control: public”);
header(“Content-Type: application/force-download”);
header(“Content-Type: application/octet-stream”);
header(“Content-Type: application/download”);
header(“Content-Description: File Transfer”);
header(“Content-Type:”.$_GET['file_extension']);
header(“Content-Disposition: attachment; filename=”.basename($_GET['file_full_path']));
header(“Content-Transfer-Encoding: binary”);
header(“Content-Length: “.sizeOf($_GET['file_full_path']));
@readfile($_GET['file_full_path']);
?>

The header name/content is very intuitive (Cache-Control: must-revalidate, etc) so it’s easy to understand.

Let’s start with the beginning:

The first 4 headers main concern is the cache control (You want the browser to download the file directly from the server not from the cache, proxy-cache ), if they are missing in browsers like ie6 or ie7 you will have problems (it’s actually a bug fix for their http protocol implementation);
-header(“Pragma: public”) // relevant only for IE6
-header(“Expires: 0″) // cache expiration time for a file
-header(“Cache-Control: must-revalidate, post-check=0, pre-check=0″); // you’re telling the cache that you want it to strictly follow your rules.
-header(“Cache-Control: public”) // marks authenticated responses as cacheable
The next 3 headers build the Force Download dialog:
-header(“Content-Type: application/force-download”);
-header(“Content-Type: application/octet-stream”);
-header(“Content-Type: application/download”);

We inform the browser that a file transfer will be initiated header(“Content-Description: File Transfer”); and the file type/extension header(“Content-Type:”.$_GET['file_extension']);
header(“Content-Disposition: attachment; filename=”.basename($_GET['file_full_path'])) forces the browser to display the download dialog and attaches a name to the file that waits to be downloaded.
I used basename($_GET['file_full_path']), to avoid another IE bug..if the name contains special characters like “/” the downloaded file name will be the actual php file ( in my case download.php…IE HAZZARD…and when you open it, you will get unmapped bytes, because of the wrong extension ).You can also put a custom name, but be careful to put the right extension.

-header(“Content-Transfer-Encoding: binary”) , means that no encoding is used
-header(“Content-Length: “.sizeOf($_GET['file_full_path'])), this entity-header field indicates the size of file, in decimal number of octets

And finally the @readfile($_GET['file_full_path']); witch reads a file and writes it on the output buffer.(mapped and encapsulated, in the download context).
I used the parameters (file_full_path, file_extension) as $_GET, because I usually use this download code in a separate file, as presented, because doing so I can avoid the “Headers already sent..” warning, and before I redirect the data to this file (GET or POST) I can process it.

NOTE: file_full_path – the relative path of the file ($_GET['file_full_path']=’ /music/music_file.mp3′)

Related Entries

Signup for our awesome Newsletter!

We will try to send you e-mail that will open your eyes in the morning and wake you up in the evening!

About the author

  • http://www.namakusurya.com Surya Adi Sapoetra

    Nice info, thanks… ;)

  • http://www.topgeldzaken.nl/lenen-zonder-bkr-toetsing/ lenen

    BKR problemen? Nu Geld lenen zonder BKR toetsing? Op zoek naar betrouwbare aanbieders? Wij vergelijken banken die u toch kunnen helpen aan een betrouwbare

  • http://www.laptopspark.com laptopspark

    i love this nice article!

  • http://www.laptopspark.com laptopspark

    we supply cheap and nice tablet pc

  • http://www.webdesigner.co.in Kate Brown

    I really liked the article. Nicely written.