I received a task that wasn’t really what I do – get a PHP file download script working – so I managed to put the following together:

<?php

// sanitize the input
$path_parts = pathinfo($_GET['f']);
$file_name  = $path_parts['basename'];
$file_path  = '../../uploads/' . $file_name;

//echo $file_path.'
'; //echo file_exists($file_path) ? 'true' : 'false' ; if (file_exists($file_path)) { // required for IE if(ini_get('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off'); } header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.$file_path.'"'); header('Expires: 0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Pragma: public'); header('Content-Length: ' . filesize($file_path)); readfile($file_path); } exit; ?>

The use case for this was allowing an end user to download an MP3 file simply by clicking a link and not by “Right-Click > Save Link As…” This was for a WordPress site so any content that was uploaded via the WordPress UI was placed in the “uploads” folder. The links to to the MP3’s were formated like so:

http://www.somewhere.com/wp-content/themes/your-theme/download.php?f=my_music.mp3

Where “download.php” is the download script displayed above and it exists within your theme folder.

The script then takes the file name (via the f name/value pair) and “cleans” it so that we know that we are only dealing with a file name and not a file name + a file system path. This is important so that the script doesn’t suffer abuse in some way.

You will notice that on line 6 there is a relative path to the location of WordPrress’ upload folder. Another point of security so that all download requests can only happen from that WordPress upload folder.

Then, on line 12 I check to see if the file exists at all. If it does then I set things up for a download.

I’m sure there are points that are missed here but this could be the basis for your own download script.