ob_implicit_flush()、flush()、ob_flush() - 无法在远程服务器上运行

ob_implicit_flush(), flush(), ob_flush() - not working on remote server

如果我从 XAMPP 上的本地服务器将此脚本加载到 chrome 中:

header("Content-Type:text/plain");

set_time_limit(0);

$max = 40;
for ($i = 0; $i < $max; $i++) {
    $response = array(  'server time: ' . date("h:i:s", time()), 'progress' => round($i/$max*100));
    echo json_encode($response);
    ob_flush();
    flush();
    sleep(1);
}
ob_clean();

如您所料,页面每秒显示一个新响应。 但是,当我将它上传到我的远程服务器时(运行 与 php 相同的版本),它会等到整个脚本完成后再显示输出。 在非常长的脚本上,它每 30-60 秒左右更新一次输出。

如标题所示,我已经尝试使用所有不同的冲洗功能,但没有任何效果。 我的本地服务器和远程服务器的 php.ini 可能有些不同,但我不知道是什么。

请帮忙。

---编辑---

我一直在做更多的测试。我注意到它确实每 4096 个字节更新一次,这恰好是我远程服务器的 php ini 值 'output_buffering' 的值。 但是,出于某种原因,如果我将 output_buffering 更改为“1”或 'off',则没有任何变化。它仍然只每 4096 字节更新一次。

我正在同一浏览器的不同服务器上测试 2 个相同的脚本。

在你需要使用之前ob_start() and ob_end_clean()。并添加 header Content-LengthTransfer-Encoding: chunked。并检查 php.ini

中的 «implicit_flush» 是否开启

为响应添加填充。检查此代码:

<?php

set_time_limit(0);
ob_start();

header('Content-Type: text/plain');

define("PADDING", 16);

//+padding
for($i=0;$i<PADDING;$i++){
    //64 spaces (1 block)
    echo str_repeat(' ', 64);
}

$max = 40;
for ($i = 0; $i < $max; $i++) {
    $response = array(  'server time: ' . date("h:i:s", time()), 'progress' => round($i/$max*100));
    echo json_encode($response);
    ob_flush();
    flush();
    sleep(1);
}
ob_end_clean();

?>

我没有考虑 nginx,它有自己的输出缓冲区。

我只是将 'header("X-Accel-Buffering: no");' 添加到 php 脚本的顶部,现在一切正常。

对我来说,添加 header('Content-Encoding: none'); 就成功了。这在使用 PHP-FPM 时是必需的。