Ok, I can't post the entire thing, but here's a download script that I wrote for a project a few months ago.
It uses PEAR::DB, db initialization is in the init.php, HZ_SelectFromTable is a wrapper for table access (handles errors and some other things and returns an array, by default it uses DB_FETCHMODE_OBJECT), HZ_Taint is essentially a wrapper for mysql_real_escape_string (plus a few other checks).
It relies on the file info (NOT the file data) previously being inserted into the database with paths.
It wouldn't take much to add a bit of code to track downloads to it.
<?php require_once("resources/includes/init.php"); if (isset($_GET['id'])){ if ($_GET['id'] != ""){ $id = HZ_Taint($_GET['id']); $file = HZ_SelectFromTable("HZ_FileList", "WHERE file_id = '".$id."'"); if (!PEAR::isError($file)){ if (count($file) > 0){ if (count($file) > 1){//if we have more than one file with exactly the same name (should never happen) header('Content-Type: text/plain'); echo "Error, file naming conflict, please contact admin with this error message and the file name you requested (".$name.")"; exit; } else { $file = $file[0];//reassign the first object in the returned array to $file since there is only one file //if it really is a regular file if (is_file($file->path)){ //if the requested file's path is not outside the base directory we set in config if (substr(realpath($file->path), 0, strlen(BASE_FILE_UPLOAD_DIR)) == BASE_FILE_UPLOAD_DIR){ $file_data = file_get_contents($file->path); $finfo = finfo_open(FILEINFO_MIME); $finfo_mime = finfo_file($finfo, $file->path); //the following headers ensure that the browser is forced to download the file, it should work on all major bowsers header('Pragma: public'); header('Last-Modified: '.gmdate('D, d M Y H:i:s') . ' GMT'); header('Cache-Control: no-store, no-cache, must-revalidate'); header('Cache-Control: pre-check=0, post-check=0, max-age=0'); header('Content-Transfer-Encoding: none'); //This should work for IE & Opera header('Content-Type: '.$file->type.'; name="'.basename($file->name).'"'); //This should work for the rest header('Content-Type: '.$file->type.'; name="'.basename($file->name).'"'); header('Content-Disposition: attachment; filename="'.basename($file->name).'"'); echo $file_data; exit; } //if substr }//if is_file }//if count == 1 }//if count > 0 }//if !PEAR::isError }//if name != "" }//if isset(name) header("Content-Type: text/plain"); echo "The file you requested cannnot be found"; exit; ?>
It uses PEAR::DB, db initialization is in the init.php, HZ_SelectFromTable is a wrapper for table access (handles errors and some other things and returns an array, by default it uses DB_FETCHMODE_OBJECT), HZ_Taint is essentially a wrapper for mysql_real_escape_string (plus a few other checks).
It relies on the file info (NOT the file data) previously being inserted into the database with paths.
It wouldn't take much to add a bit of code to track downloads to it.