如何在PHP中下载大于2GB的文件?

4
我正在尝试用PHP编写一个脚本来下载一个大的zip文件(2,663,439,370字节),但遇到了一个有趣但令人沮丧的问题:该脚本下载了前2,147,483,647个字节,然后继续下载文件,但不是从字节号2,147,483,648、2,147,483,649等开始附加它,而是从字节号1开始附加字节到文件中。
所以,下载的文件由这些字节组成:字节1、字节2、...字节2,147,483,647、字节1、字节2...依此类推。
我注意到2,147,483,647是32位系统可以存储的最大整数值。然而,我的服务器是64位系统,可以存储比那更大的值。为了证明这一点,var_dump((int) 2147483648)返回正确的整数。
我的下载脚本是尽可能正确的(从php.net复制粘贴而来)。
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="Certificat.zip"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($zipname));    

readfile($zipname);

有人遇到过这个问题吗?

似乎PHP设置了一些软限制? - Praveen Kumar Purushothaman
1
你的系统可能是64位的,但看起来你的PHP肯定不是。一个64位的整数最大只能达到9223372036854775807 - MonkeyZeus
1
无论如何,如果您完全访问服务器并且它是Apache,则请查看mod_xsendfile。 - MonkeyZeus
3个回答

1

阅读5.6源代码,readfile返回RETURN_LONG(size)这是源代码的参考

进一步挖掘,这个宏似乎处理长整型定义,通常为4个字节,给出了有符号整数的最大值,你的函数在那里停止。我没有深入挖掘,这是我的假设,鉴于您正在经历的行为,这对我来说已经足够了(但对于某些人可能不够严谨)。

另一方面,我个人从未使用过readfilefopen/fread组合在性能和内存使用方面总是更好。因为你可以读取块,而不是吞下2GB的庞然大物,这对服务器资源来说更容易。


0

我不确定这对你有帮助,但是你应该移除header('Content-Length: ' . filesize($zipname));。在从正在进行的流中加载时,我曾经多次这样做,浏览器会一直加载,直到脚本停止响应内容。我不确定它是否适用于这个大文件,它可能会达到PHP限制。


1
通过这样做,它只是从浏览器中隐藏了文件大小,无法估计下载时间,但结果是相同的。 - Marius Popescu

0

最后,我通过消除readfile()函数,并使用fopen()fread()自己输出文件内容来解决了这个问题。

然而,当处理如此大的文件时,readfile()失败的原因仍然是一个开放的话题(我已经阅读了php.net上的文档,但没有找到任何关于这个问题的说明)。所以,我还在等待那位有经验的程序员为我指点迷津 :)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接