All Posts in hacks

July 13, 2012 - Comments Off on How to Force a Download in Drupal

How to Force a Download in Drupal

Drupal is a great CMS when it comes to managing files. The large variety of extant modules allow you to support pretty much any file type you can imagine in your back end. However, browser to browser, many file types are treated quite differently. The most problematic culprit being, of course, images as all browsers view them in the window by default. So how can you cause a link to force an image download to the user's computer when it comes to such finicky files? Try the following script I adapted from one found on eLouai.


// ** http://www.*MYSITE*.com/*path to this script*/force-download.php?file=*file path NB: must be in same directory or child directory as this script*

$filename = $_GET['file'];
$filename = preg_replace("/.*/files//", '', $filename);

// required for IE, otherwise Content-disposition is ignored
if(ini_get('zlib.output_compression'))
ini_set('zlib.output_compression', 'Off');

// addition by Jorg Weske
$file_extension = strtolower(substr(strrchr($filename,"."),1));

if( $filename == "" )
{
echo "ERROR: download file NOT SPECIFIED."; exit; } elseif ( ! file_exists( $filename ) ) { echo "ERROR: File not found, please go back and try another file.
$filename"; exit; }; switch( $file_extension ) { case "pdf": $ctype="application/pdf"; break; case "exe": $ctype="application/octet-stream"; break; case "zip": $ctype="application/zip"; break; case "doc": $ctype="application/msword"; break; case "xls": $ctype="application/vnd.ms-excel"; break; case "ppt": $ctype="application/vnd.ms-powerpoint"; break; case "gif": $ctype="image/gif"; break; case "png": $ctype="image/png"; break; case "jpeg": case "jpg": $ctype="image/jpg"; break; default: $ctype="application/force-download"; } header("Pragma: public"); // required header("Expires: 0"); header("Cache-Control: must-revalidate, post-check=0, pre-check=0"); header("Cache-Control: private",false); // required for certain browsers header("Content-Type: $ctype"); // change, added quotes to allow spaces in filenames, by Rajkumar Singh header("Content-Disposition: attachment; filename="".basename($filename)."";" ); header("Content-Transfer-Encoding: binary"); header("Content-Length: ".filesize($filename)); readfile("$filename"); exit();

?>

Place the following script in your files directory of your Drupal installation (our default being "sites/theme/default/files"). The script needs to be in a common root of all the files you wish users to be able to download. This is due to the only major addition to the code I made, the preg_replace on line 9. This essentially deletes anything that comes before the "files" directory in the path leaving just the rest of the file path.

While you could remove this line and put the script in your root, this could be a serious security gap so I do not recommend doing so. Moreover, restricting downloads to specific directories is useful if you want to prevent users from using the script to easily download certain files outside of the script's parent directory. You can move the script to any folder that contains your expected targets and change line 9 as below with your chosen directory replacing "files" (or in this case "**YOUR FILE DIRECTORY**").

$filename = preg_replace("/.*/**YOUR FILE DIRECTORY**//", '', $filename);

While you're at it, feel free to replace the error messages with whatever you feel is appropriate. Note that this script currently supports pdf, exe, zip, doc, xls, ppt, gif, png, jpeg and jpg file types though you can easily add more exotic file types. I'd caution against including any web related extensions (especially php) to prevent users from potentially using the script to download your source files.

To then use this script simply make your links as follows:

Force Download

Or if you have your file's URI, which you should, do this:

Force Download

Remember, such a script gives even a semi-savvy user incredible access to your site's file structure so be careful how and where you use this. If placed in the incorrect directory, a user could potentially download your source files.

Published by: benchirlin in The Programming Mechanism
Tags: ,