有没有办法在不超出PHP内存的情况下向浏览器发送大型(大约> 700mb)文件?
我尝试使用fpassthru
和readfile
,但它超出了内存限制。
答案 0 :(得分:8)
最有效的解决方案是使用X-Sendfile标头,如果您的网络服务器支持它。
这意味着您无需在提供文件时占用PHP,只需发送标头并让Web服务器处理它。
示例(来自Apache mod_xsendfile页面:)
header("X-Sendfile: $path_to_somefile");
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$somefile\"");
exit;
答案 1 :(得分:4)
好老fopen()+ fread()+ fclose():
<?php
$handle = fopen('/tmp/foo', 'rb');
while (!feof($handle)) {
echo fread($handle, 8192);
}
fclose($handle);
8192
是PHP文档中显示的缓冲区大小,但根据我的经验,最好提高它,因为您可以以极少的内存使用量为代价获得有趣的性能提升。
答案 2 :(得分:3)
听起来你使用fpassthru时遇到的问题是由于整个文件被加载到内存中。你应该做的是使用块读取文件数据传统的fopen / fread / fclose周期,随时输出数据。
例如:
<?php
$fileRes = fopen('/path/to/your/file.data', 'rb');
if(is_resource($fileRes) {
while (!feof($fileRes)) {
echo fread($fileRes);
}
fclose($fileRes);
}
else die("Couldn't open file...");
?>
答案 3 :(得分:0)
fpassthru
(与readfile
一样)直接发送数据,而没有太多的内存分配。
因此,缓存和ob_end_flush
中的问题会有所帮助:
<?php
$fp = fopen($filename, 'rb');
header('Content-Type: ' . mime_type($filename));
header("Content-Length: " . filesize($filename));
ob_end_flush()
fpassthru($fp);
exit;