4

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

我在我的根目录之外向事先经过验证的人提供了一个 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) . '"');

任何帮助或建议将不胜感激。谢谢!

4

1 回答 1

2

我建议看看这个评论:

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

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

当我将非常大的文件发送给下载速度非常慢的客户端时,我开始遇到麻烦。在这些情况下,脚本会超时并且下载会因文件不完整而终止。我坚决反对禁用脚本超时——只要是解决编程问题的方法,你就做错了——所以我试图根据文件的大小来调整超时。但最终失败了,因为无法预测最终用户下载文件的速度,所以这实际上只是一个最好的猜测,所以不可避免地我们仍然会收到脚本超时的报告。

然后我偶然发现了一个很棒的 Apache 模块,叫做 mod_xsendfile(https://tn123.org/mod_xsendfile/(二进制文件)或 https://github.com/nmaier/mod_xsendfile(源代码))。该模块主要监视输出缓冲区中是否存在特殊标头,当找到它们时,它会触发 apache 自行发送文件,就像用户直接请求文件一样。PHP 处理在此时停止,因此无论文件大小或客户端下载速度如何,都不会出现超时错误。并且终端客户端可以获得 Apache 发送文件的全部好处,例如准确的文件大小报告和下载状态栏。

我最终得到的代码太长了,无法在此处发布,但通常使用 mod_xsendfile 模块(如果存在),如果不存在,则脚本回退到使用我最初发布的代码。您可以在https://gist.github.com/854168找到一些示例代码

编辑

只是为了参考将“分块”链接到原始代码的代码

<?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; 
} 
?>
于 2012-09-13T17:47:23.453 回答