所以我试图通过PHP脚本提供大型文件,它们不在Web可访问的目录中,所以这是我能够提供访问它们的最佳方式.
我能想到用来提供这个文件的唯一方法是将它加载到内存(fopen,fread等),将头数据设置为正确的MIME类型,然后只回显文件的全部内容.
这个问题是,我必须同时将这些~700MB的文件加载到内存中,并保留整个内容直到下载完成.如果我可以在他们下载的时候输入我需要的部分,那将是很好的.
有任何想法吗?
你不需要阅读整个内容 - 只需输入一个循环读取它,比如32Kb块并将其作为输出发送.更好的是,使用fpassthru为你做同样的事情....
$name = 'mybigfile.zip'; $fp = fopen($name, 'rb'); // send the right headers header("Content-Type: application/zip"); header("Content-Length: " . filesize($name)); // dump the file and stop the script fpassthru($fp); exit;
如果你使用readfile,甚至更少的行,这不需要fopen调用...
$name = 'mybigfile.zip'; // send the right headers header("Content-Type: application/zip"); header("Content-Length: " . filesize($name)); // dump the file and stop the script readfile($name); exit;
如果您想要更加可靠,您可以支持Content-Range标头,该标头允许客户端请求文件的特定字节范围.这对于将PDF文件提供给Adobe Acrobat特别有用,Adobe Acrobat只需要请求呈现当前页面所需文件的块.这有点牵扯,但请看这个例子.
使用php发送大文件的最佳方法是X-Sendfile
标题.它允许Web服务器通过零拷贝机制更快地提供文件sendfile(2)
.它受lighttpd和带有插件的 apache的支持.
例:
$file = "/absolute/path/to/file"; // can be protected by .htaccess header('X-Sendfile: '.$file); header('Content-type: application/octet-stream'); header('Content-Disposition: attachment; filename="'.basename($file).'"'); // other headers ... exit;
服务器读取X-Sendfile
标头并发送文件.
虽然fpassthru()
过去是我的第一选择,但PHP手册实际上建议使用*readfile()
,如果您只是将文件按原样转储到客户端.
*
"如果你只是想将文件的内容转储到输出缓冲区,而不先修改它或寻找特定的偏移量,你可能想要使用readfile(),它可以节省你的fopen()调用." - PHP手册