PHP: Prompt The User To Download A Specific File

This is a function which allows you to prompt the user to download a specific file with any filename you like. This will also not render the file inline (like those direct PDF links most of us don’t like) but it will display a file dialog asking the user to either download or save the file.

I apologize for the bad code formatting but that WordPress plugin I’m using for code highlighting is driving me crazy.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
/**
* Prompts the user to download a file in the browser.
* Works even with IE6.
*
* @param string $path                   The file path to the file to be downloaded
* @param string $browserFilename        The name sent to the browser
* @param string $mimeType               The mime type like 'image/png'
*
* @return void
*/
function promptToDownload($path, $browserFilename, $mimeType)
{
if (!file_exists($path) || !is_readable($path)) {
return null;
}

header("Content-Type: " . $mimeType);
header("Content-Disposition: attachment; filename=\"$browserFilename\"");
header('Expires: ' . gmdate('D, d M Y H:i:s', gmmktime() - 3600) . ' GMT');
header("Content-Length: " . filesize($path));

// If you wish you can add some code here to track or log the download

// Special headers for IE 6
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');

$fp = fopen($path, "r");
fpassthru($fp);
}

Here is how to use the function:

1
promptToDownload(dirname(__FILE__).'/info.pdf', 'download.pdf', 'application/pdf');

The first parameter is the path to the file to be downloaded, the second is the name of the file as the user’s browser shall display it. The third parameter is the MIME type of the file. Here is a list of many MIME types.

Security Warning!

Never use any path provided directly by the user. You should never write something like this:

1
promptToDownload($_GET['path']'download.pdf', 'application/pdf');

This would allow the user to download arbitrary content from your server, even files like /etc/passwd!

So instead of using code as shown above you should put all of the files you are making available for download into one directory and only use the filename itself as a parameter like this:

1
promptToDownload(dirname(__FILE__).'/files/'.basename($_GET['file'])'download.pdf', 'application/pdf');

Internet Explorer 6 Problems

When using the code above and your PHP file is named download.php Internet Explorer 6 may not use the filename download.pdf but show “download.php” instead so it might be useful to use an Apache RewriteRule so that the browser sees a .pdf file extension instead. But this should only be a problem for you if you still want to support an outdated and insecure browser.

tweetthis-15

Be Sociable, Share!
August 11th, 2010 at 1:10 am

Sascha,

This is some great, clean code. Thank you! I’m using it for a site wherein I look to make it easier to ‘cleanup’ audio using SOX… I need to ‘send’ the fixed audio back — I’m using some of your ideas (and some code) from this blog to make it quick-and-easy. Thanks a ton!

David

Comments are closed.

Sascha Kimmel - Living The Web Experience Since 1996 by tricosmedia