如何优雅地告诉客户端传输完成,浏览器会立即显示页面?

时间:2013-07-16 01:34:36

标签: php connection flush ob-start

问候家伙,

我正在研究我的php框架。它有一个响应管理器来包装php的头文件,cookie和缓冲区函数。我用它将结果页面发送给用户。

但是,即使页面标题和内容已经使用ob_start发送 - > ob_end_flush - >刷新,浏览器仍然挂起并等待脚本完成。

当我想做一些缓慢的工作,如更新当前用户的会话或只是发送邮件或上传某些内容时,它会导致问题。用户必须等到一切都完成,即使他们已经拥有包括标题的整个页面。

我想知道的是,如何让浏览器知道页面已完全加载,所以它现在可以显示页面?

谢谢!

////////////////////////////废弃的解决方案///////////////// ///////////

废弃的解决方案1 ​​

过去,我通常使用ob_start - >的组合。 ob_end_flush - > ob_flush - >刷新修复这个问题,似乎会​​这样:

function send($content) {
    ob_start();

    echo $content;

    ob_end_flush();
    ob_flush();
    flush();

    return true;
}

但是 ob_flush会抛出一个E_NOTICE,说它有“没有要冲洗的缓冲区”。我不想通过静音这个E_NOTICE来解决这个问题(,事实上,在我的框架中,没有办法将任何错误静音)。所以这不是解决这个问题的方法。

弃置解决方案2

我也尝试在发送内容后关闭连接,代码会这样:

function send($content) {
    ob_start();

    header('Connection: close');

    echo $content;

    ob_end_flush();

    flush();

    return true;
}

它可以解决任何错误的问题,但它带来了另一个问题:看到客户端的连接将在收到页面后关闭,当他们想要打开另一个页面时,他们必须重新连接。这将在网络上产生额外负载。

弃置解决方案3

是的,有些人建议我使用fastcgi,并使用fastcgi_finish_request();但我想让我的代码在环境之间更加兼容,所以它实际上不是一个选项。

1 个答案:

答案 0 :(得分:0)

IIS 上,您无法在fastcgi完成之前断开连接。您需要使用fascgi_finish_request()^手动强制完成当前CGI

Apache 上,您可以使用Content-Length: 0 redirect trick^,但效果很好但不适用于IIS (至少不符合我的经验)

PS :并确保执行ignore_user_abort(true)并在任何这些之前延长运行时限制set_time_limit(0) (infinte)以防止PHP从客户端关闭连接时关闭。

PPS :发送页面后运行的任务应进入 cronjobs 。这是更清洁的做事方式。