我的网络主机有一个“进程杀手”,可以终止任何运行时间超过5分钟的进程,因此我的下载脚本无法运行那么久。
我以为我会使用fread-print几秒钟,只是为了捕获用户是否最初中止下载,然后使用fpassthru来转储文件的其余部分。
ob_end_clean();
$file = fopen($this->m_path,'rb'); // read binary
fseek($file, $startByte);
$cnt = 0;
while (!feof($file) && (!connection_aborted()) && ($bytesSent<$bytesToSend) )
{
$cnt++;
if($cnt > 25) // to simulate breaking the loop after a certain time has passed
break;
set_time_limit(0);
$buffer = fread($file, 32*1024);
print($buffer);
//flush();
$bytesSent += strlen($buffer);
}
flush(); // has no effect on fpassthru
// --- insert point for the code below --
if(!feof($file))
{
fpassthru($file);
}
fclose($file);
问题是fpassthru在整个下载过程中保持脚本运行。我已经厌倦了使用输出缓冲,导致脚本快速退出,但下载在大约8分钟后被切断(我以15 kB / s的速度发送30 MB文件)。
如果我在上面的“插入点”插入以下内容,那么使脚本快速退出并让下载完成的一件事是:
echo("X"); // or pretty much any string literal
flush();
它每次都有效,但文件当然会被破坏(正如预期的那样)。
如果我插入这样的东西:
echo fread($file, 16);
flush();
它不起作用(fpassthru不允许脚本退出)。
感觉就像我尝试了一切。我累了关闭并重新打开文件,睡觉,多次调用flush。对我来说,当我打印字符串文字时,为什么它会突然起作用,这几乎没有任何意义。
PHP版本5.2.11 Apache 2.2.9
编辑:
我最终让我的网络主机将超时时间延长到40分钟,以便我可以使用fread-echo提供文件,并且干净利落地退出。我提供相对较小的文件,并且为少数访问者提供了恢复服务。
我还制作了(并拒绝了)基于重定向的解决方案,我在.htaccess中设置了我想要的标头,但是这个解决方案会迫使我禁止部分下载,因为我在计算使用的带宽时遇到了问题。
答案 0 :(得分:2)
我看到了两个直接解决问题的方法:
header('Location: '.$actualFile, true, 303)
(303表示“查看其他资源”,以防止帖子数据再次发布到下一个网址)之后您可以exit;