Sending correct file size with PHP download script
I created a file download script in PHP, it works, but web browsers report the file as "Unknown Length". My code is as follows:
function downloadFile($file){
// Set up the download system...
header('Content-Description: File Transfer');
header('Content-Type: '.mime_content_type($file));
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));
// Flush the cache
ob_clean();
flush();
// Send file to browser
readfile($file);
// DO NOT DO ANYTHING AFTER FILE DOWNLOAD
exit;
}
Originally from http://paul.luminos.nl/update/471:
The CrimsonBase website verifies downloads by passing them through a robust PHP script similar to the one published by Andrew Johnson in his article about PHP-controlled file downloads.
Andrew makes a very important comment at the end of the article:
"If you compress files with Zlib, mod_deflate and so on the Content-Length header won't be accurate so you'll end up seeing "Unknown size" and "Unknown time remaining" when downloading files."
I would like to stress this: if your browser doesn't appear to be obeying the headers generated by your PHP script—especially
Content-Length
—it is fairly likely that Apache'smod_deflate
extension is enabled.You can easily disable it for a single script using the following line in an applicable
.htaccess
file:SetEnvIfNoCase Request_URI ^/download\.php no-gzip dont-vary
where download.php is here assumed to be in the download script located in the server's root directory path (e.g.
www.crimsonbase.com/download.php
). (That's because the regular expression is^/download\.php
.)
I had this same problem, and I fixed it by sending the Content-Length
header before the Content-Disposition
.
header('Content-Type: video/mp4');
header("Content-Transfer-Encoding: Binary");
header("Content-Length: ".filesize($file_url));
header("Content-disposition: attachment; filename=\"" . basename($file_url) . "\"");
readfile($file_url);