使用 PHP 下载脚本发送正确的文件大小

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1972642/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-25 04:30:16  来源:igfitidea点击:

Sending correct file size with PHP download script

phpcross-browserbrowserdownload

提问by Rocket Hazmat

I created a file download script in PHP, it works, but web browsers report the file as "Unknown Length". My code is as follows:

我在 PHP 中创建了一个文件下载脚本,它可以工作,但是网络浏览器将该文件报告为“未知长度”。我的代码如下:

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;
}

回答by Honso

Originally from http://paul.luminos.nl/update/471:

最初来自http://paul.luminos.nl/update/471

The CrimsonBase websiteverifies 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's mod_deflateextension is enabled.

You can easily disable it for a single script using the following line in an applicable .htaccessfile:

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.)

CrimsonBase网站验证下载使它们通过类似于安德鲁·约翰逊在发布的一个强大的PHP脚本他对PHP控制文件下载的文章

安德鲁在文章的最后做了一个非常重要的评论:

“如果您使用 Zlib、mod_deflate 等压缩文件,则 Content-Length 标头将不准确,因此您最终会在下载文件时看到“未知大小”和“剩余时间未知”。”

我想强调这一点:如果您的浏览器似乎没有遵守由您的 PHP 脚本生成的标头——尤其是Content-Length——很可能mod_deflate启用了 Apache 的扩展。

您可以使用适用.htaccess文件中的以下行轻松为单个脚本禁用它:

SetEnvIfNoCase Request_URI ^/download\.php no-gzip dont-vary

这里假定 download.php 位于位于服务器根目录路径(例如www.crimsonbase.com/download.php)中的下载脚本中。(那是因为正则表达式是^/download\.php.)

回答by Skylar Ittner

I had this same problem, and I fixed it by sending the Content-Lengthheader before the Content-Disposition.

我遇到了同样的问题,我通过Content-LengthContent-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);

回答by Rocket Hazmat

Try not flushing the cache before readfile() function. My code is almost identical to yours otherwise, and works fine.

尽量不要在 readfile() 函数之前刷新缓存。我的代码与您的代码几乎相同,并且工作正常。