PHP中的fpassthru

时间:2010-02-28 16:03:17

标签: php download

我的网络主机有一个“进程杀手”,可以终止任何运行时间超过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中设置了我想要的标头,但是这个解决方案会迫使我禁止部分下载,因为我在计算使用的带宽时遇到了问题。

1 个答案:

答案 0 :(得分:2)

我看到了两个直接解决问题的方法:

  1. 获取另一个不做那种东西的主持人
  2. 不要让脚本管理下载,而是让apache执行此操作,只需在更新计数器后重定向到实际文件等。 header('Location: '.$actualFile, true, 303)(303表示“查看其他资源”,以防止帖子数据再次发布到下一个网址)之后您可以exit;