这将一次显示一行,暂停 2 秒。
(在 IEx 和 Firefox 中进行了测试)
<?php
如果 (ob_get_level() == 0) ob_start();
对于 ($i = 0; $i<10; $i++){
echo "<br> 应显示的行.";
echo str_pad('',4096)."\n";
ob_flush();
flush();
sleep(2);
}
echo "完成.";
ob_end_flush();
?>
(PHP 4,PHP 5,PHP 7,PHP 8)
flush — 清空系统输出缓冲区
刷新 PHP 和 PHP 使用的后端(例如:CGI,Web 服务器)的系统写入缓冲区。在命令行环境中,flush() 只尝试刷新缓冲区的内容,而在 Web 上下文中,将刷新缓冲区的内容和标头。
请注意: flush() 可能无法覆盖 Web 服务器的缓冲方案,并且它对浏览器中的任何客户端端缓冲都没有影响。
请注意: 此函数对用户级输出处理程序没有任何影响,例如由 ob_start()或 output_add_rewrite_var()启动的输出处理程序。
flush() 可能妨碍在 Web 上下文中设置并发送标头的输出处理程序(例如 ob_gzhandler()),原因是其在这些处理程序可以进行此操作之前发送标头。
此函数没有参数。
不返回值。
这将一次显示一行,暂停 2 秒。
(在 IEx 和 Firefox 中进行了测试)
<?php
如果 (ob_get_level() == 0) ob_start();
对于 ($i = 0; $i<10; $i++){
echo "<br> 应显示的行.";
echo str_pad('',4096)."\n";
ob_flush();
flush();
sleep(2);
}
echo "完成.";
ob_end_flush();
?>
这是我用来关闭几乎任何可能导致不需要的输出缓冲并打开隐示刷新功能的功能
<?php
@apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);
对于 ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
ob_implicit_flush(1);
?>
虽然它仍然失败,但请记住,在渐增式渲染启动之前,Internet Explorer 和 Safari 有一个 1k 缓冲,所以你也需要输出一些填充内容。
如果你想在从 Apache httpd 与 mod_proxy_fcgi 使用 php-fpm 时使刷新正常工作,自 2.4.31 起,你可以追加 flushpackets=on 以启用刷新功能(默认情况下是即时的),以及 flushwait=n(n 以毫秒为单位),以将刷新时间延迟几次性能秒。
这些值可以追加到 <Proxy> 指令,例如 <Proxy "fcgi://localhost/" flushpackets=on flushwait=500> 或在 ProxyPass 和 ProxyPassMatch 行中。
2.4 的 mod_proxy_fcgi 文档没有记录这些内容,但可以在 2.5 或 trunk 文档中找到它们。
我想指出,有一个函数可以替代 ob_flush 和 flush。如果你在页面的最顶部设置 ob_implicit_flush(true); 它会自动清空脚本剩余部分中的任何 echo 或 print。
注意,仍然需要最少数量的数据通过浏览器过滤器。我建议使用 str_pad($text,4096); 因为它会自动将文本长度扩展到 4 KB,在使用 FireFox 和 linux 时,这是最低限制。
我希望这些在一定程度上有所帮助。
关于浏览器的缓冲,可以使用
$out=str_pad($yourMessage.'<br/>',1024);
print($out);
ob_flush();
flush();
在 Firefox 60 ESR 中适用于我。
对于使用 IIS 的 Windows 系统,ResponseBufferLimit 优先于 PHP 的 output_buffering 设置。因此,还必须将 ResponseBufferLimit 设置为低于其默认值。
对于低于 7 的 IIS 版本,该设置可以在 %windir%\System32\inetsrv\fcgiext.ini 文件(FastCGI 配置文件)中找到。可以将相应的行设置为
ResponseBufferLimit=0
对于 IIS 7+,该设置存储在 %windir%\System32\inetsrv\config 中。编辑 applicationHost.config 文件,并搜索 PHP_via_FastCGI(假设你已经按照安装说明将 PHP 安装为 FastCGI 模块,名称为 PHP_via_FastCGI)。在 add 标记内,在末尾放置以下设置
responseBufferLimit="0"
因此,整行将类似于
<add name="PHP_via_FastCGI" path="*.php" verb="*" modules="FastCgiModule" scriptProcessor="C:\PHP\php-cgi.exe" resourceType="Either" responseBufferLimit="0" />
或者,可以使用以下命令插入设置
%windir%\system32\inetsrv\appcmd.exe set config /section:handlers "/[name='PHP_via_FastCGI'].ResponseBufferLimit:0"
将 PHP 与 CGI/FastCGI 模块一起使用时,有一个新缓冲区(由 mod_fcgid 初始化,默认大小为 65536 字节)。这会导致 `flush()` 和 `ob_flush()` 在使用 implicit_flush(true) 时不能按预期工作。
在 mod_fcgid 配置中设置“OutputBufferSize 0”可以解决此问题。
希望有帮助!
大家好。
尽管我尝试了 strpad 4096 字符,所有的头都没有问题,既有 TABLE 也有没有 TABLE,每次 flush 和 ob_flush 之后都没有获得刷新后的数据,而是仍然是空白页面。尝试在刷新之前添加一个 sleep(1) 之后,所有问题都迎刃而解。
/Mikael
在 PHP 网站、谷歌和各种论坛搜索后,都没有办法找到我的脚本在调用 flush 和 ob_flush 时不输出任何内容的解决方案,我想到尝试让 PHP 调用
session_write_close();
在开始 echo 之前。这种方法非常有效。我找不到任何与此相关的内容,希望此说明对以后的人有所帮助。
与 IE 一样,Safari 显示任何信息之前需要大量数据,实际上比 Explorer 需要的数据还要多。以下代码适用于 Firefox 和 Safari,也应该适用于 IE。
<?php
for($i = 0; $i < 40000; $i++)
{
echo ' '; // 额外的空格
}
// 让内容持续传送到浏览器?
flush();
// 50000 微秒可以让 Safari、IE、Firefox 等浏览器持续接收内容
usleep(50000);
?>
这段代码出自一篇讨论浏览器功能和 flush() 的博客评论
如果 flush() 函数不起作用。必须在 php.ini 中设置以下选项
--[code]--
output_buffering = Off
;output_handler =
zlib.output_compression = Off
;zlib.output_handler =
--[^code^]--
如果不起作用,那么必须在服务器中查看 Header 并检查 `Server` 字符串。
就我而言,前端是 Nginx Web 服务器,后端是 Apache。
因此,必须在 Nginx 配置文件中禁用缓冲。
若要停止缓冲,必须向配置文件添加以下字符串
--[code]--
proxy_buffering off;
--[^code^]--
然后重新启动 Nginx 守护程序。可以在 nginx 网站的文档中找到有关配置的更多信息。
结合了一些想法,我终于能够获得一个长期运行的脚本,以让我实时了解它正在执行的操作。这是一个使用 PHP 作为 cgi 运行的 wamp 设置。我相当肯定 apache 没有任何缓冲输出,因为它试图提供帮助。同样希望提供帮助,我希望此示例解决方案对某些人有帮助。
<?php
// thx mandor at mandor
ini_set('max_execution_time', 0);
ini_set('implicit_flush', 1);
ob_implicit_flush(1);
echo 'doing something'; my_flush();
sleep(5);
echo 'doing something else'; my_flush();
sleep(5);
echo 'finally done - hooray';
function my_flush() {
// following matt at hevanet's lead
for ($i=0;$i<10000;$i++) echo ' ';
ob_flush();
flush();
}
在尝试让 flush 在我的 windows 计算机上工作时遇到了许多问题,在阅读了每个人的帖子后终于找到了解决方法,它不起作用。
1) 将 output_buffering = 0
2) 将 zlib.output_compression = 0
然后我使用 Wireshark 监视网络数据包,确实服务器正在传输数据,但浏览器没有显示数据。因此,这是一个浏览器缓冲问题(我在使用 Firefox 13)
对我来说,我需要发送大约 1k 的数据才会显示数据。为了做到这一点,我添加了更多标题信息…
在 php.ini 中,我将 default_charset = "utf-8"
这样就足以解决缓冲问题。
你还可以尝试执行
echo str_repeat(" ", 1024), "\n";
在脚本的开头。
希望对你有帮助
这是 Rusty 以下评论的扩展
在这花了好几个小时试图让 IE6 在页面中间刷新数据(它在 Firefox 中工作得很好),我终于搞清楚了问题。除非包含数据的表格是完整的,否则 IE 不会显示刷新后的数据(即使有)。
您想让 IE 显示的每个新元素都必须不在任何表格中。您必须结束所有表格。
使用 flush() 函数有点复杂,您必须多做一些实验。
因此,如果您设计了一个在最后通过表单数据输入(数据提交)调用其他网站的时间循环,那么您就有
向缓冲区发出一些内容以快速加载新网站。
例如
<?php
$instant=gettimeofday();
$timenow=$instant["sec"];// 开始时间
// 时间循环(例如在 30 分钟之后进行安全性保存)
while (1) { echo "<b></b>";// 无用(仅在快速加载下一个网站
// 或在切换时加载同一网站)
flush(); // 输出缓冲区
$instant=gettimeofday();
$timeactual=$instant["sec"]; // 以秒为单位获取实际时间
$flag=(($timeactual>$timenow+$diff)? 1:0);//$diff=切换时间
if ($flag) { what_do_at_switch_Time();// 秒级保存等
$timenow=$timeactual; } // 设置新的开始时间
sleep(5); // 大概...(很重要)
} // 结束 while 循环
?>
因此,您可以在您的网站中规划一个安全性保存或其他函数,如果您进行切换,则上传新网站或相同网站(被调用的网站)有效...
我花了数天的时间来弄清为什么自动刷新突然间就失灵了,因为它以前一直运行得很好。显然,是 McAfee Spamkiller 导致了问题。禁用它不起作用,我必须彻底删除它。希望这能对某人有所帮助。
如果您没有明确使用缓冲功能,那么 ob_flush() 只有在 php.ini 文件中启用了输出缓冲时才需要。
flush() 只有在 php.ini 文件中关闭了 implicit_flush 时才需要。将 implicit_flush 设置为 on 将消除对所有这些 flush() 调用需求,但它通常只在受极严格控制的环境中才有效。在生产环境中启用 implicit_flush 可能很糟糕。
这帮助我使自动刷新起作用。
使用带有 deflate 的 apache。
为此脚本关闭压缩:(将其添加到脚本的顶部某处)
apache_setenv('no-gzip', '1');
但是,此方法仅在 php 作为模块而不是 cgi 扩展运行并且必须禁用安全模式时才有效。
您还可以通过创建一个 .htaccess 文件并添加以下项来关闭目录的压缩
mod_gzip_on Off
但这样会影响整个目录。
希望我能提供帮助。
与 apache 2.4.57 结合使用 php8.3-fpm
为了在浏览器中启用自动刷新,您需要发送更多一些数据(每次自动刷新至少 4096 字节),并且需要为该站点添加一个设置到 apache2 配置的虚拟主机
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php/php8.3-fpm.sock|fcgi://localhost"
</FilesMatch>
<Proxy fcgi://localhost/">
ProxySet enablereuse=on flushpackets=on
</Proxy>
您好,
我在将 javascript 发送给 <body></body> 内容已发送到浏览器之后遇到了同样的问题(此脚本更新 iframe 的内容)。
以下两种解决方案对我有效
- 添加足够的数据(即:额外的虚拟文本,例如空格),或
- 在页面的结尾处回显 '</body>' 标记
请注意,对于后一种方法,一个人应该
- 在 php.ini 中关闭 output_buffering,并
* 在其 php.ini 中打开 implicit_flush,或
* 在脚本的开头调用 ob_implicit_flush();
我更愿意在结尾处回显 '</body>' 标记,因为它不需要通过网络发送任何额外的数据,并且它是一种更加简洁的编码技术。
备注
- 这些解决方法在使用 perl 和 cgi 时不需要...
- 你可以打开 php.ini 中的 zlib.output_compression
亲切的问候,希望这有帮助。
Maurits
我已经想出一个方法来创建一个对大部分平台通用的进度条。因为我的灵感源自这个网站,因此我也有义务回馈社区。
注意:浏览器缓冲的一个有趣现象... 对于 Firefox 和某些其他浏览器,你需要使用 <html><body> 根据它们的 ID 来识别 Javascript 中的项。所以我建议在调用此函数之前使用某种头函数。
<?php
函数 fn_progress_bar($intCurrentCount = 100, $intTotalCount = 100)
{
static $intNumberRuns = 0;
static $intDisplayedCurrentPercent = 0;
$strProgressBar = '';
$dblPercentIncrease = (100 / $intTotalCount);
$intCurrentPercent = intval($intCurrentCount * $dblPercentIncrease);
$intNumberRuns++;
if(1 == $intNumberRuns)
{
$strProgressBar = <<< BAR
<table width='50%' id='progress_bar' summary='progress_bar' align='center'><tbody><tr>
<td id='progress_bar_complete' width='0%' align='center' style='background:#CCFFCC;'> </td>
<td style='background:#FFCCCC;'> </td>
</tr></tbody></table>
<script type='text/javascript' language='javascript'>
function dhd_fn_progress_bar_update(intCurrentPercent)
{
document.getElementById('progress_bar_complete').style.width = intCurrentPercent+'%';
document.getElementById('progress_bar_complete').innerHTML = intCurrentPercent+'%';
}
</script>
BAR;
}
else if($intDisplayedCurrentPercent <> $intCurrentPercent)
{
$intDisplayedCurrentPercent = $intCurrentPercent;
$strProgressBar = <<< BAR
<script type='text/javascript' language='javascript'>
dhd_fn_progress_bar_update($intCurrentPercent);
</script>
BAR;
}
if(100 <= $intCurrentPercent)
{
$intNumberRuns = $intDisplayedCurrentPercent = 0;
$strProgressBar = <<< BAR
<script type='text/javascript' language='javascript'>
document.getElementById('progress_bar').style.visibility='hidden';
</script>
BAR;
}
echo $strProgressBar;
flush();
ob_flush();
}
?>