我在服务器上有一个PHP脚本将文件发送给配方:它们获得一个唯一的链接,然后他们可以下载大文件.有时传输出现问题,文件已损坏或永不完成.我想知道是否有更好的方法来发送大文件
码:
$f = fopen(DOWNLOAD_DIR.$database[$_REQUEST['fid']]['filePath'], 'r');
while(!feof($f)){
print fgets($f, 1024);
}
fclose($f);
Run Code Online (Sandbox Code Playgroud)
我见过的功能如
http_send_file
http_send_data
Run Code Online (Sandbox Code Playgroud)
但我不确定他们是否会奏效.
解决这个问题的最佳方法是什么?
问候
erwing
gar*_*row 11
如果您要发送真正大的文件并担心它会产生的影响,您可以使用x-sendfile头.
从SOQ 使用-xsendfile-with-apache-php,一个howto blog.adaniels.nl:how-i-php-x-sendfile /
小智 8
最好的解决方案是依赖lighty或apache,但如果在PHP中,我会使用PEAR的HTTP_Download(不需要重新发明轮子等),有一些不错的功能,如:
请参阅介绍/使用文档.
文件分块是PHP最快/最简单的方法,如果你不能或不想使用一些更专业的像卷曲,mod-xsendfile
在阿帕奇或一些专门的脚本.
$filename = $filePath.$filename;
$chunksize = 5 * (1024 * 1024); //5 MB (= 5 242 880 bytes) per one chunk of file.
if(file_exists($filename))
{
set_time_limit(300);
$size = intval(sprintf("%u", filesize($filename)));
header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.$size);
header('Content-Disposition: attachment;filename="'.basename($filename).'"');
if($size > $chunksize)
{
$handle = fopen($filename, 'rb');
while (!feof($handle))
{
print(@fread($handle, $chunksize));
ob_flush();
flush();
}
fclose($handle);
}
else readfile($path);
exit;
}
else echo 'File "'.$filename.'" does not exist!';
Run Code Online (Sandbox Code Playgroud)
来自richnetapps.com/NeedBee.在200 MB文件上进行测试readfile()
,即使设置了最大允许内存限制,也会死亡,这1G
比下载文件大小多五倍.
顺便说一句:我也在文件上对此进行了测试>2GB
,但PHP只设法先写入2GB
文件,然后断开连接.与文件相关的函数(fopen,fread,fseek)使用INT,因此你最终达到了极限2GB
.mod-xsendfile
在这种情况下,上述解决方案(即)似乎是唯一的选择.
编辑:让自己100% ,你的文件保存在utf-8
.如果省略,则下载的文件将被破坏.这是因为此解决方案用于print
将文件块推送到浏览器.
我们一直在几个项目中使用它,到目前为止它工作得很好:
/**
* Copy a file's content to php://output.
*
* @param string $filename
* @return void
*/
protected function _output($filename)
{
$filesize = filesize($filename);
$chunksize = 4096;
if($filesize > $chunksize)
{
$srcStream = fopen($filename, 'rb');
$dstStream = fopen('php://output', 'wb');
$offset = 0;
while(!feof($srcStream)) {
$offset += stream_copy_to_stream($srcStream, $dstStream, $chunksize, $offset);
}
fclose($dstStream);
fclose($srcStream);
}
else
{
// stream_copy_to_stream behaves() strange when filesize > chunksize.
// Seems to never hit the EOF.
// On the other handside file_get_contents() is not scalable.
// Therefore we only use file_get_contents() on small files.
echo file_get_contents($filename);
}
}
Run Code Online (Sandbox Code Playgroud)
对于下载文件,我能想到的最简单的方法是将文件放在临时位置,并为它们提供一个可以通过常规 HTTP 下载的唯一 URL。
作为生成这些链接的一部分,您还可以删除超过 X 小时的文件。
归档时间: |
|
查看次数: |
43693 次 |
最近记录: |