php - 对于连接速度慢的人来说,下载用 PHP 提供的大型(ish)zip 文件会损坏

标签 php download zip shared-hosting x-sendfile

我是新手,所以我会尽力解释我遇到的问题。如果有遗漏或不清楚的地方,我提前道歉。

我在我的根目录外为事先经过验证的人提供了一个 81MB 的 zip 文件。我收到有关下载损坏或无法完成下载的报告。如果我模拟慢速连接,我已经在我的机器上验证了这种情况。

我在运行 Apache-Coyote/1.1 的共享主机上。

我收到网络超时错误。我认为如果下载时间过长,我的主机可能会终止下载,但他们尚未通过任何一种方式进行验证。

我以为我可能遇到了内存限制或时间限制,所以我的主机安装了 apache 模块 XSendFile。我在验证后处理下载的文件中的标题是这样设置的:

<?php
set_time_limit(0);
$file = '/absolute/path/to/myzip/myzip.zip';

header("X-Sendfile: $file");
header("Content-type: application/zip");
header('Content-Disposition: attachment; filename="' . basename($file) . '"');

如有任何帮助或建议,我们将不胜感激。谢谢!

最佳答案

我建议看看这条评论:

http://www.php.net/manual/en/function.readfile.php#99406

特别是如果您使用的是 apache。如果不是,上面链接中的代码应该会有帮助:

I started running into trouble when I had really large files being sent to clients with really slow download speeds. In those cases, the script would time out and the download would terminate with an incomplete file. I am dead-set against disabling script timeouts - any time that is the solution to a programming problem, you are doing something wrong - so I attempted to scale the timeout based on the size of the file. That ultimately failed though because it was impossible to predict the speed at which the end user would be downloading the file at, so it was really just a best guess so inevitably we still get reports of script timeouts.

Then I stumbled across a fantastic Apache module called mod_xsendfile ( https://tn123.org/mod_xsendfile/ (binaries) or https://github.com/nmaier/mod_xsendfile (source)). This module basically monitors the output buffer for the presence of special headers, and when it finds them it triggers apache to send the file on its own, almost as if the user requested the file directly. PHP processing is halted at that point, so no timeout errors regardless of the size of the file or the download speed of the client. And the end client gets the full benefits of Apache sending the file, such as an accurate file size report and download status bar.

The code I finally ended up with is too long to post here, but in general is uses the mod_xsendfile module if it is present, and if not the script falls back to using the code I originally posted. You can find some example code at https://gist.github.com/854168

编辑

只是为了引用执行“分块”的代码 Link to Original Code :

<?php 
function readfile_chunked ($filename,$type='array') { 
  $chunk_array=array(); 
  $chunksize = 1*(1024*1024); // how many bytes per chunk 
  $buffer = ''; 
  $handle = fopen($filename, 'rb'); 
  if ($handle === false) { 
   return false; 
  } 
  while (!feof($handle)) { 
      switch($type) 
      { 
          case'array': 
          // Returns Lines Array like file() 
          $lines[] = fgets($handle, $chunksize); 
          break; 
          case'string': 
          // Returns Lines String like file_get_contents() 
          $lines = fread($handle, $chunksize); 
          break; 
      } 
  } 
   fclose($handle); 
   return $lines; 
} 
?>

关于php - 对于连接速度慢的人来说,下载用 PHP 提供的大型(ish)zip 文件会损坏,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12411822/

相关文章:

javascript - php和js重定向错误

php - 将外部脚本添加到一个 Magento 页面

php - 速率函数的问题

c# - 读取 zip 包中 xml 文件的内容

python - 如何在python中减去两个列表

python - 使用 Python 安全地提取 zip 或 tar

javascript - 使用 AJAX 设置间隔

javascript - 有没有办法强制网站加载较轻的版本?

download - 将视频保存到 CameraRoll React-Native

powershell - 使用 PowerShell FTP 下载多个文件