【问题标题】:Large .zip files download incomplete大型 .zip 文件下载不完整
【发布时间】:2014-12-07 22:27:23
【问题描述】:

我是一个严重的新手,但在发帖之前我做了很多研究,所以希望你能提供帮助。

我正在尝试提供托管在 Apache 服务器上的大型 .zip 文件,大约 6.4 Gb。该文件在浏览器中显示完整下载,但实际上只下载了大约 500Mb。这似乎是一个非常普遍的问题,并且在网上找到了很多其他帖子和信息,但这个问题对我来说一直存在。

Large Zip file offered for download using php

IE download incomplete even though it claims success

Large zip downloads failing only in IE

我一直在使用 Chrome 39.0.2171.71 进行测试,但我在使用 FireFox 和 IE 时遇到了同样的问题。我认为我的文件比其他人发布的文件要大得多,因此他们的解决方案可能有助于解决问题,但没有解决根本问题。我有一个大约 400Mb 的第二个 .zip 文件,并且我成功使用了相同的 http 标头。

我发现的最有用的文章是:http://perishablepress.com/http-headers-file-downloads/,我已经从该来源复制了下面显示的大部分 php,因为该网站上的其他海报似乎已经这样做了。

我也尝试过使用 X-SendFile,但我认为我的虚拟主机没有安装适当的 Apache 模块。我花了一整天的时间在这上面工作,并且已经没有想法了!我已经成功使用了下载管理器,我不知道这是偶然还是什么,但我不想要求我的客户必须下载并安装单独的程序才能获取 .zip 文件。

<?php 
// HTTP Headers for ZIP File Downloads

// set example variables
$filename = "huge.zip";
$filepath = "****";

// http headers for zip downloads
// header("X-Sendfile: $filepath$filename");
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"".$filename."\"");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".filesize($filepath.$filename));
set_time_limit(0);
ob_end_flush();
@readfile($filepath.$filename);
?>

这是我运行上面的 php 时的响应标头

远程地址:76.162.142.242 请求网址:****/GetSW.php 请求方法:GET 状态码:200 OK 请求标头 接受:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 接受编码:gzip、deflate、sdch 接受语言:en-US,en;q=0.8 授权:基本****** 连接:保持活动 饼干:_ga=GA1.2.1176828605.1417985823 DNT:1 主办方:www.teamursa.org 参考:http://www.teamursa.org/****.html 用户代理:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.71 Safari/537.36 响应标头 缓存控制:公共 连接:保活 内容描述:文件传输 内容处置:附件;文件名="巨大的.zip" 内容长度:6720560824 内容传输编码:二进制 内容类型:应用程序/八位字节流 日期:2014 年 12 月 7 日星期日 22:16:57 GMT 过期:0 保活:超时=3,最大值=120 语用:public 服务器:阿帕奇 X-Powered-By:PHP/5.2.17

【问题讨论】:

  • 首先你不应该让 PHP 处理文件发送。而不是readfile() 将实际传输委托给Apache,这确实是应该使用mod_xsendfile 的地方。您的 PHP 脚本没有实现部分/字节范围传输,因此恢复了 HTTP 下载。在 PHP 中重新实现任何这些都是非常不值得的。 -- 那么 PHP 脚本包装器的最初原因是什么?
  • ftp 比 http 传输更大的文件友好,如果你有那个选项的话
  • 我最好的猜测是你的 php 脚本会因为 max_execution_time 设置 php.net/manual/en/info.configuration.php#ini.max-execution-time 而被杀死。因此,您的浏览器会得到 readfile 在那个时间窗口内设法发送的内容。
  • 感谢 cmets!我添加并删除了 max_execution_time 设置,但没有任何效果。 FTP 很好用,但我不希望人们必须下载和安装 FTP 客户端。 @mario我可以尝试看看我的网络主机是否可以为我安装 mod_xsendfile ,我不确定这涉及到什么或者他们是否会这样做。我猜我不知道除了 php 包装器还能做什么。以前我只是在我的 html 中有一个指向 huge.zip 文件的链接,但 php 似乎是一种比使用 .htaccess 文件更有效的方式来指定 http 标头。
  • 如果只是关于附加标头,请使用mod_cern_meta 和一个单独的huge.zip.meta 文件,其中列出了要添加的原始HTTP 标头。或者,整个文件夹的 RewriteRule huge.zip - [T=archive/zip] 或普通的 Header add "Content-Disposition: attachment"

标签: php apache http http-headers zip


【解决方案1】:

您可能需要增加服务器上的内存限制。在打开 PHP 标记之后尝试以下操作

ini_set('memory_limit','16M');

从 1600 万开始不断增加

【讨论】:

  • readfile 不会缓冲整个文件甚至更大的部分。它专门设计用于从文件句柄直接通过管道传输到 CGI/STDOUT 流。
  • @mario 啊。我看到 readfile 不会导致任何内存问题。我的错。我忽略了这一点
  • 我已经读过输出缓冲可能是一个问题,我相信我没有在上面粘贴的代码中使用它,对吗?我试图找到让我认为输出缓冲不适合我的情况的帖子,但目前无法放置。
【解决方案2】:

我建议您尝试使用网络浏览器直接下载文件,这意味着您转到文件存储的地址。例如 www.example.com/downloads/download.zip 希望这会有所帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 1970-01-01
    • 1970-01-01
    • 2012-04-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多