PHP实现即时将结果输出到浏览器
web开发中有没有碰到需要适时的将结果输出到浏览器页面而不刷新整个页面的需求呢?当你在处理一个过程需要耗时很长,但你又需要适时的知道程序当前的处理状况的时候,该怎么办呢?下面就分享一下如何使用php及时的输出当前结果到浏览器而不刷新整个页面的效果吧。
下面以一个简单的例子来说明这个问题。首先来看一段代码:
<?php
for($i=0;$i<10;$i++){
echo $i;
sleep(1);
}
?>面这段程序如果在PHP解释器中执行,每秒会输出一个数,和预计效果一样。但在浏览器中访问时,结果却是浏览器在十秒之后一次性地显示了所有结果。对于这个问题,我们可以使用 ob_flush() 和 flush() 来强制刷新浏览器缓存,程序改为:
<?php
//author www.phpernote.com
for($i=0;$i<10;$i++){
echo $i;
ob_flush();
flush();
sleep(1);
}
?>问题解决,但又出来个问题,浏览器还不兼容了。实际测试中只有 Firefox 按预计效果即时输出了结果,而在 IE Safari Opera 等浏览器中还是一次性的输出结果。查阅相关资料发现是因为不同的浏览器对缓冲的处理方式不同,Firefox 在被要求强制刷新缓存时很听话,而IE需要在接收到256个字节后才会将内容即时展现在界面上,Safari 需要1024个字节,Opera 更有个性,只有在遇到HTML标签的时候才会即时输出(Safari也是如此)。
对于以上问题,针对IE和Safari,可以在输出结果之前先输出大于限定数目的空白字符:
<?php
echo str_repeat(" ",1024);
for($i=0;$i<10;$i++){
echo $i;
ob_flush();
flush();
sleep(1);
}
?>而对于Opera、Safari遇到HTML标签后才会即时输出的问题,由于一般我们不会只往浏览器中输出纯文本内容,故可以不作考虑。对于上面的程序,可以在输出结果中加入HTML标签来达到目的:
<?php
echo str_repeat(" ",1024);
for($i=0;$i<10;$i++){
echo $i."<br>";
ob_flush();
flush();
sleep(1);
}
?>PHP 里开启实时输出方法是 ob_implicit_flush() ,
但它大部分情况下都不管用,
因为 php.ini 配置里 output_buffering 输出缓冲大部分是 On 开启的,
还有 zlib.output_compression 也经常会被开启,
除了 PHP 这一层,还有 Nginx 的缓冲设置 proxy_buffering ,和压缩 gzip 也大都是开启的。
为了一两个页面的需求,修改整个服务器的网站配置,恐怕没有人会做这种选择。
这里推荐一下简单的方法:
set_time_limit(0);
ob_end_clean();
ob_implicit_flush();
header('X-Accel-Buffering: no'); // 关键是加了这一行。
echo '现在是:'.date('H:i:s').'<br>';
sleep(5);
echo '五秒后:'.date('H:i:s');
Refer:php-fpm 实时输出
