Using a .htaccess file with deny from all
will stop people accessing that folder, It wont stop php from accessing it, but you could put your files one directory lower then your htdocs/www/public_html
folder and use php to grab and serve thos files.
With passing a parameter eg: ?id=1
you would access the 1
with $_GET['id']
you would need to check if the file exists, add some http headers to force the download.
Heres a simple example you can work on:
<?php
//your below webroot downloads folder
$path="/var/www/somehost.com/downloads/";
//An array created from globing the download directory or from a database source
$files=array('somefile.gif',
'someotherFile.png');
//In my example the id is the key to the file pathe array so 0 would be somefile.gif and 1 would be the next.
if(isset($_GET['id'])){
//Is it numeric?
if(is_numeric($_GET['id']) && isset($files[$_GET['id']])){
//Download the file, the download function will return error on fail, eg: not found or directory
$status = download($path.$files[$_GET['id']]);
//Spit out the error
if(isset($status['error'])){
die($status['error']);
}
}
}
function download($file,$chunk=1024){
if (file_exists($file)) {
if(is_dir($file)){return array('error'=>'Not allowed!');}
//Set content headers to force download.
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.str_ireplace(' ','_',basename($file)).'"');
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
//If download is larger the 2GB, alls not lost
header('Content-Length: '.sprintf("%u", filesize($file)));
//Clean the buffer
ob_clean();
//Open a handle to the file
$handle = fopen($file, "rb");
$chunksize=(sprintf("%u", filesize($file))/$chunk);
set_time_limit(0);
//Loop through the file
while (!feof($handle)) {
//Echo a piece of the file out
echo fgets($handle, $chunksize);
flush();
}
fclose($handle);
die;
}else{return array('error'=>'Not found!');}
return;
}
?>
You would also need to check user permission on the file, but thats another question.