I'm setting up MP3 downloads on my site, and want people to click a link in an email to download a ZIP file of MP3s. I'd like the URL they click to not point directly to the file, so that I don't reveal the actual location – I might also add a time limit to the download etc.
So I'd been using readfile($file_url) and trying a lot of header() options but wasn't getting very far. Then I read you can just use:
header("Location: " . $file_url);
This seems to work OK in the browsers I've tested. Is there any downside of doing it this way versus readfile($file_url)?
Thanks!
No serious issue, just you actually reveal actual location of the file (attacker may try to guess addresses of files he should not have access to), client will have to make additional request to the server (delaying download just a few miliseconds) and sometimes, webbrowser have a bad day and decides to not follow the relocation for various reasons.
On bright side, this way you don't need to process the file through PHP, saving a tiny bit of server's resources (which is very questionable as readfile() function is pretty optimalized, compared to processing a new http request)
Back to your original problem, when serving file for download through PHP, you don't need anything more then 3 lines from following example:
<?php
//code copied from http://php.net/manual/en/function.header.php
// We'll be outputting a PDF
header('Content-type: application/pdf');
// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');
// The PDF source is in files/originalfile.pdf
readfile('files/originalfile.pdf');
?>
Just make sure to not print any string (not even UTF8 BOM characters from your source code) before using Header() function <- frequent problem.
"Downsides" depends on what you're trying to accomplish.
By setting the Location
header, you're sending a redirect. The browser, indeed, will receive a response with HTTP status code 302 ("Found") and the new URL of the resource. Basically, you're redirecting them to another resource.
In order for this to work, the resource you're redirecting them to must be publicly accessible. That is: it needs to be an existing document inside the "document root" of your server.
This approach has certain characteristics that, depending on your requirements, may be considered as downsides:
/var/www/public
, you may want to put these files in a non accessible folder, like /var/www/resources
, and serve them only through your PHP scripts. If these "characteristics" are not good for you, then you may want to avoid using the Location
header.
Some PHP code to serve MP3 files can be:
$file = 'local/path/to/your_audio_file.mp3'; // the path on the local file system - ie. don't use "http://www.example.com"!
header('Content-Description: File Transfer');
header('Content-Type: audio/mpeg'); // audio/mpeg is the correct mime type for mp3 files
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit; // Could be a good idea to exit at the end
Some of the headers may be redundant, but they're to assure the best cross-browser compatibility. I took them (and then adapted) from http://php.net/manual/en/function.readfile.php
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.