Using PHP Headers to Force Download
Often, when creating a website, you may encounter a situation in which you would like to provide a file download. All common sense tells us that in order to provide such to the user, we simply need to create a link to the file itself on our server. The problem in this simplistic method lies in the fact that every browser, platform, etc., may handle various file types in their own distinct manner.
For instance, say you have an mp3 of your newest hit single that you would like to share with site visitors. You can link to this file by simply creating a link:
<a href="mysong.mp3">Download My Hit Single</a>
The problem with this method is that most browsers have the capability to play an mp3 file. Therefore, they will automatically load up their Quicktime, etc. plug-in and start progressively downloading the file. This is not going to get that file on your site visitor's hard drive like you originally intended. Well thanks to the wonderful language of PHP, we can quickly change this behavior or our site visitors' browsers.
The example I use below is the method I use to provide the download for the Ryboe Tag Cloud Widget for WordPress, available for download here.
The magical function to do so is the header() function. This function allows us to define raw HTTP headers as a string. The script will then execute those headers and force the browser to render the page accordingly.
First things first… we need to define the path to our file in PHP (as a string).
<?PHP
// Define the path to file
$file = 'ryboe_tag_cloud.zip';
?>
Now that we have our file path defined, we should check to make sure that it actually exists before going any further. If the file doesn't exist we will output an error to the browser screen.
if(!file_exists($file)))
{
die('Error: File not found.');
}
Now that we have passed this check, time to move onto the second part of our boolean statement in which we define all of our headers.
else
{
// Set headers
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$file");
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
}
Most of these header parameters are pretty self explanatory. The critical ones here are the File Transfer, attachment, and application/zip definitions. The "Content-Description: File Transfer" will help force a download for the user. By defining a "Content-Disposition: attachment" in the next line, we tell the browser that we are indeed going to link to a file. The next line, "Content-Type", tells the browser what type of application association we want the browser to reference.
Now that we have all of these headers set, what do we do? Well simply put, we open the file using the readfile() function. This will actually be place inside of the else curly brackets.
// Read the file from disk
readfile($file);
The final code looks like:
<?PHP
// Define the path to file
$file = 'ryboe_tag_cloud.zip';
if(!file)
{
// File doesn't exist, output error
die('file not found');
}
else
{
// Set headers
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$file");
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
// Read the file from disk
readfile($file);
}
?>
So there you have it, forcing file downloads through a PHP file. This actually opens a lot of avenues in your application writing as you can now make your downloads dynamic and even add advanced stat tracking through a database.
Related Tutorial: Protect Downloadable Files with .htaccess Rules


