I have files stored outside the public_html folder for security purposes. However, I would like to link to specific files somehow where a user could download one of these fi
Another standard way to do this is using mod_xsendfile -- it will allow a web application to have the web server send a file as its output by specifying the path in a header (X-SendFile).
You can use method like this one to return file contents and file information headers to users browser, just make sure that nothing else is outputted before this.
I suggest that you put this to separate file and call that for example download.php
.
function returnFile( $filename ) {
// Check if file exists, if it is not here return false:
if ( !file_exists( $filename )) return false;
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
// Suggest better filename for browser to use when saving file:
header('Content-Disposition: attachment; filename='.basename($filename));
header('Content-Transfer-Encoding: binary');
// Caching headers:
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
// This should be set:
header('Content-Length: ' . filesize($filename));
// Clean output buffer without sending it, alternatively you can do ob_end_clean(); to also turn off buffering.
ob_clean();
// And flush buffers, don't know actually why but php manual seems recommending it:
flush();
// Read file and output it's contents:
readfile( $filename );
// You need to exit after that or at least make sure that anything other is not echoed out:
exit;
}
// Added to download.php
if (isset($_GET['file'])) {
$filename = '/home/username/public_files/'.$_GET['file'];
returnFile( $filename );
}
This is basic example and does not take into account that user may try to take some evil advantages of $_GET
that is not properly sanitized.
This means basically that user can for example retrieve passwd
file or some other sensitive information if certain conditions apply.
For example, retrieving /etc/passwd
:
Just point browser to http://server.com/download.php?file=../../../etc/passwd
and server returns that file. So before real use you should find out how to properly check and sanitize any user supplied arguments.
It is not possible to for paths outside the public_html
.
mod_rewrite
only rewrites the request, but the path still should be available to the users.