0

问候伙计们,

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

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

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

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

谢谢!

//////////////////////////////////////////////////////////////////// ////////

废弃的解决方案 1

过去,我通常使用 ob_start -> ob_end_flush -> ob_flush -> 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(); 但我想让我的代码在环境之间更兼容,所以它实际上不是一个选项。

4

1 回答 1

0

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

Apache上,您可以使用Content-Length: 0 重定向技巧^,它效果很好,但在 IIS 上不起作用(至少在我的经验中没有)

PS:并确保在任何这些操作之前执行ignore_user_abort(true)并扩展运行时限制set_time_limit(0)(无限),以防止 PHP 在客户端关闭连接时关闭。

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

于 2013-07-16T02:10:48.707 回答