【问题标题】:fpassthru in PHPPHP中的fpassthru
【发布时间】: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 中设置了我想要的标头,但该解决方案将迫使我在大多数情况下禁止部分下载,因为我在计算使用的带宽时遇到了问题。

【问题讨论】:

    标签: php download


    【解决方案1】:

    我看到您的问题的两个直接解决方案:

    1. 换一个不做这种事情的主机
    2. 不要让脚本管理下载,而是让 apache 来做,只需在更新计数器等后重定向到实际文件。 header('Location: '.$actualFile, true, 303)(303 表示“查看其他资源”,以防止帖子数据再次发布到下一个 url)之后您可以 exit;

    【讨论】:

    • 感谢您的回答。我已经确认重定向到文件有效。它没有给我想要的控制权,但如果我无法让脚本正常工作,它就是备用计划。
    • 你也可以实现测距,查看thomthom.net/blog/2007/09/php-resumable-download-server的例子。这意味着您的脚本永远不会一次执行整个文件。
    • 上面的代码中没有显示,但是我已经实现了对部分下载的支持,但是如果请求的段不能在时限内下载,那就无济于事了。跨度>
    猜你喜欢
    • 1970-01-01
    • 2015-08-28
    • 2014-02-12
    • 2012-07-21
    • 1970-01-01
    • 1970-01-01
    • 2020-09-23
    • 2016-04-23
    • 2023-04-06
    相关资源
    最近更新 更多