【发布时间】:2012-12-25 08:00:33
【问题描述】:
我的网络主机有一个“进程杀手”,它会终止任何运行时间超过 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 阿帕奇 2.2.9
编辑:
我最终让我的网络主机将超时时间延长到 40 分钟,这样我就可以使用 fread-echo 提供文件,并在有空闲时间的情况下干净地退出。我提供相对较小的文件,并且为少数被切断传输的访问者支持恢复。
我还提出(并拒绝)了一个基于重定向的解决方案,我在 .htaccess 中设置了我想要的标头,但该解决方案将迫使我在大多数情况下禁止部分下载,因为我在计算使用的带宽时遇到了问题。
【问题讨论】: