had problems flushing tables to screen.
this worked for me
<?
if (ob_get_level() == 0) ob_start();
loop{
tables and stuff
echo str_pad("<br>\n",8);
}
ob_flush();
flush(); // needed ob_flush
usleep(50000);// delay minimum of .05 seconds to allow ie to flush to screen
?>
flush
(PHP 4, PHP 5)
flush — 出力バッファをフラッシュする
説明
void flush ( void )PHP および PHP が使っている(CGI, Web サーバなどの)バックエンドの 出力バッファをフラッシュします。これにより、それまでの全ての 出力がユーザのブラウザに対して効率的に出力されます。
flush() は、Webサーバまたはクライアント側の ブラウザのバッファリングの手法に影響を与えません。 そのため、出力バッファをフラッシュするには ob_flush() および flush() の両方をコールする必要があります。
いくつかのサーバ、特に Win32 上ではスクリプトからの出力をブラウザに 結果を送信する前にスクリプトが終了するまでバッファに溜めることがあります。
mod_gzip のような Apache 用のサーバモジュールはそれ自体がバッファリングを行います。 そのため、flush() をコールしても 即時にデータをクライアントに送信しないという結果につながります。
ブラウザ側で表示前に入力をバッファリングすることもあり得ます。 Netscape では例えば改行または開始タグを受信するまでテキストは バッファリングされ、最も外側のテーブルの </table> タグが現れるまでテーブルは描画されません。
いくつかのバージョンの Microsoft Internet Explorer は、256 バイトの 出力を受けてからページを表示し始めます。このため、これらのブラウザに ページを表示させるには、フラッシュする前に余分な空白を送信する 必要があるかもしれません。
返り値
値を返しません。
flush
27-Jun-2007 10:57
13-May-2007 07:13
Hello,
I had the same problems with sending a javascript after the <body></body> content has been sent to the browser (the script updates the content of an iframe).
Two solutions work for me:
- add enough data (i.e.: extra dummy text like spaces) or,
- echo the '</body>' tag at the end of the page
Note, that for the latter to work one should:
- turn of output_buffering in php.ini and either:
* turn on implicit_flush in its php.ini or,
* call ob_implicit_flush(); at the beginning of a script
I preferr echoing the '</body>' tag at the end as it doesn't require any extra data to be sent over the wire and its much a neater coding technique.
Notes:
- these worakarounds aren't needed when using perl and cgi,... .
- you can leave the zlib.output_compression in your php.ini switched on
Kind regards and hoped this is of any help.
Maurits
24-Apr-2007 04:17
If flush() don't work remember to check if you have any antivirus caching the data sent to the browser.
30-Mar-2007 09:14
I've spent days trying to figure out why flush didn't work all of a sudden, while it used to work perfectly. Apparently, it was McAfee Spamkiller that caused problems. Disabling it didn't work, I had to completely remove it. Hope this helps someone.
07-Feb-2007 05:25
If you're not explictly using the buffering functions, then ob_flush() is only necessary if output buffering is turned on in your php.ini file.
flush() is only necessary if implicit_flush is turned off in your php.ini file. Setting implicit_flush to on will remove the need for all these flush() calls, but it's generally only good in an extremely controlled environment. Turning on implicit_flush in a production environment can be bad.
11-Nov-2006 07:42
Also, if you don't have a global php.ini file, PHP will laugh at you for calling flush()... and so will I.
04-Aug-2006 03:51
ob_flush();flush();
Not the other way around, because it wont work.
05-Apr-2006 10:46
Sorry if this is off topic, but it's the closest place I could find :) I had an issue with essentially running a CPU intensive task while updating the browser with a progress bar via javascript and flushing the buffer a lot.
When the script was running, it effectively blocked other pages from running. I had a few extra httpd_preforks processes just waiting to be used, but they just sat there. I wasn't reading a file, locking database tables or anything that I would suspect an exclusive lock on, just outputting a bunch of text to the browser. I even tried throttling my loops to see if it was processor related but still had problems.
Finally, I found this in the php.ini file and changed the On to Off and it worked.
[Sockets]
; Use the system read() function instead of the php_read() wrapper.
sockets.use_system_read = Off
Posting in case someone else has the same issue (or if someone knows why this would make a difference :) ).
25-Nov-2005 08:54
If flush is not working probably mod_gzip is enabled.
To disable it just add following lines to .htaccess
<IfModule mod_gzip.c>
mod_gzip_on no
</IfModule>
21-Nov-2005 12:06
<?php
header('Content-type: multipart/x-mixed-replace;boundary=endofsection');
print "\n--endofsection\n";
$pmt = array("-", "\\", "|", "/" );
for( $i = 0; $i <10; $i ++ ){
sleep(1);
print "Content-type: text/plain\n\n";
print "Part $i\t".$pmt[$i % 4];
print "--endofsection\n";
ob_flush();
flush();
}
print "Content-type: text/plain\n\n";
print "The end\n";
print "--endofsection--\n";
?>
Server Push with "multipart/x-mixed-replace", tested on Firefox 1.07.
This is an example requiring both ob_flush and flush.
03-Oct-2005 05:47
Hi all.
Been scratching my head over data NOT flushed to IE (6) even though I tried strpad 4096 chars, all headers OK, TABLE and no TABLE, flush and ob_flush - still a blank page. Tried adding a sleep(1) before flushing - and everything worked as a charm.
/Mikael
In my testing, Internet Explorer 6.0 wouldn't flush anything nested in <table> or <td> tags, regardless of padding. But at the <body> level everything flushed with no fuss -- no padding or tags required.
Both Firefox 1.0 and Safari 2.0 could flush within tables, and both required a tag after the text (like <br>). Safari could flush only after the first 1024 characters where received. Firefox needed at least 8 characters per flush (but it could flush anything at the <body> level).
So the only thing that worked on all those browsers was this:
<html>
<body>
<?php // not in table tags for IE
echo str_pad('',1024); // minimum start for Safari
for ($i=10; $i>0; $i--) {
echo str_pad("$i<br>\n",8);
// tag after text for Safari & Firefox
// 8 char minimum for Firefox
flush(); // worked without ob_flush() for me
sleep(1);
}
?>
</body>
</html>
09-Aug-2005 05:15
So will this:
<?php
for ($i = 0; $i<10; $i++){
echo "<br> Line to show.";
echo str_pad('',4096)."\n";
flush();
sleep(2);
}
echo "Done.";
?>
I've not found a case where I need to use ob_flush() if I never started caching the buffer in the first place.
There seems to be some confusion you have to start buffering the output to make sure you flush it later with both commands.
If you don't need to buffer with ob_*, only flush() is enough in my experience.
17-Jul-2005 03:41
This will show each line at a time with a pause of 2 seconds.
(Tested under IEx and Firefox)
<?php
if (ob_get_level() == 0) ob_start();
for ($i = 0; $i<10; $i++){
echo "<br> Line to show.";
echo str_pad('',4096)."\n";
ob_flush();
flush();
sleep(2);
}
echo "Done.";
ob_end_flush();
?>
13-Jul-2005 10:54
I find that you need to open your ob for it to print . Heres my example that works in IE . Yes - the strings need to be long for it to flush ...
ob_start();
for($i = 1; $i <= 10; $i++){
$sourceName = 'filetoupload' . $i;
$imageArray = array();
if(!is_uploaded_file($_FILES[$sourceName]['tmp_name'])) { $imageArray[$num-1] = NULL; $message="Image $i does not exist (has not been prompted for upload)<br/>"; }
else {
move_uploaded_file($_FILES[$sourceName]['tmp_name'], "temporary/$sourceName");
$message = "Image $i has been uploaded to the server";
}
echo $message;
flush();
ob_flush();
usleep(300);
}
ob_end_flush();
02-Jun-2005 11:37
The documentation for flush() states:
flush() has no effect on the buffering scheme of your webserver or the browser on the client side. Thus you need to call both ob_flush() and flush() to flush the output buffers.
What it does not state is the order in which the functions should be called. This is the correct order:
ob_flush();
flush();
These functions do not need to be called repeatedly (as other have stated), merely in the correct order.
16-May-2005 08:38
It is a bit complicated to work with the funktion flush() and you have to experiment with it a bit.
So if you design a site which has a timeloop at the end that calls a other site via a form data input (Data Submit) you have
to give something out to the buffer to get that new site loaden quick.
For example:
$instant=gettimeofday();
$timenow=$instant["sec"];//Start Time
//timeloop(e.g. for security_save after 30 min)
while (1) { echo "<b></b>";//Useless (only to quickload next
//or same Site when do a switch)
flush(); //giveout buffer
$instant=gettimeofday();
$timeactual=$instant["sec"]; //get Actual Time in Secs
$flag=(($timeactual>$timenow+$diff)? 1:0);//$diff=switchTime
if ($flag) { what_do_at_switch_Time();//Sec.Save etc.etc.
$timenow=$timeactual; } //Set new Start Time
sleep(5); //Or so...(Important)
} //End of while-Loop
So you can programm a security save or other function in your site and if you do a switch the upload of the new or same site (the called site) works...
22-Apr-2005 06:35
Modified progress bar.. Works in IE, Mozilla+FF.
<html>
<head>
<style type="text/css"><!--
div {
margin: 1px;
height: 20px;
padding: 1px;
border: 1px solid #000;
width: 275px;
background: #fff;
color: #000;
float: left;
clear: right;
top: 38px;
z-index: 9
}
.percents {
background: #FFF;
border: 1px solid #CCC;
margin: 1px;
height: 20px;
position:absolute;
width:275px;
z-index:10;
left: 10px;
top: 38px;
text-align: center;
}
.blocks {
background: #EEE;
border: 1px solid #CCC;
margin: 1px;
height: 20px;
width: 10px;
position: absolute;
z-index:11;
left: 12px;
top: 38px;
filter: alpha(opacity=50);
-moz-opacity: 0.5;
opacity: 0.5;
-khtml-opacity: .5
}
-->
</style>
</head>
<body>
<?php
if (ob_get_level() == 0) {
ob_start();
}
echo str_pad('Loading... ',4096)."<br />\n";
for ($i = 0; $i < 25; $i++) {
$d = $d + 11;
$m=$d+10;
//This div will show loading percents
echo '<div class="percents">' . $i*4 . '% complete</div>';
//This div will show progress bar
echo '<div class="blocks" style="left: '.$d.'px"> </div>';
flush();
ob_flush();
sleep(1);
}
ob_end_flush();
?>
<div class="percents" style="z-index:12">Done.</div>
</body>
</html>
17-Apr-2005 12:25
Remember when trying to output partial content, that PHP's .ini file setting affects whether or not it succeeds, depending on how you code it, of course. Here's an example using a progress bar done soley in PHP:
// Some HTML/CSS to spice up the spaces...
<html>
<head>
<style type="text/css"><!--
.pbar {
background: #EEE;
border: 1px solid #CCC;
margin: 1px;
height: 10px;
width: 10px;
}--></style>
</head>
<body>
<?php
// If the buffer is not set to 0, there's no need to call
// ob_start(), because the buffer is started already.
// You can test that by a call to ob_get_level();. Calling it
// again will cause a second level of buffering to start and
// the script won't work.
if (ob_get_level() == 0) {
ob_start();
}
echo str_pad('Loading... ',4096)."<br />\n";
for ($i = 0; $i < 25; $i++) {
echo '<span class="pbar"> </span>';
ob_flush();
usleep(700000);
}
ob_end_flush();
// Close it out...
?>
</body>
</html>
Note: This is just an example. Normally it's bad practice to use the OB like this :)
This was tested with PHP 5.04 on WinXP Pro/IIS 5.1
15-Apr-2005 12:33
This is an extention of Rusty's comment below:
After sitting here for hours trying to make IE6 flush data out in the middle of a page (with it working perfectly in Firefox), I finally figured out the problem. IE will not display flushed data (even if it has it) unless the table that contains it is complete.
Every new element you want IE to display must not be in ANY kind of table at all. You must end all your tables.
07-Apr-2005 08:45
I would like to point out that there is a function to replace ob_flush and flush. If you set ob_implicit_flush(true); at the top of the page it will automatically flush any echo or print you do in the rest of the script.
Note that you still need a minimum amount of data to come through the browser filter. I would advice using str_pad($text,4096); since this automatically lenghtens the text with spaces to 4 KB which is the minimum limit when using FireFox and linux.
I hope this helps you all out a bit.
22-Mar-2005 03:42
Like IE, Safari needs a fair amount of data before it'll display anything, actually more than explorer. The following code works for me in Firefox and Safari, and should work in IE as well.
<?php
for($i = 0; $i < 40000; $i++)
{
echo ' '; // extra spaces
}
// keeps it flowing to the browser
flush();
// 50000 microseconds keeps things flowing in safari, IE, firefox, etc
usleep(50000);
?>
This code came from a comment on a blog discussing browser functionality with flush();
05-Mar-2005 08:28
I figured out a way to create a simple progress bar that is for the most part cross platform. Seeing as I got my ideas from this site it's only share to give back to the community.
Note: Something interesting about browser buffering... you have to have the <html><body> for Firefox and some other browsers to recognize items by their id in Javascript. So I recommend using some sort of header function before calling this function.
<?php
function 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();
}
?>
05-Mar-2005 12:54
After searching through the PHP site, google and various forums, not finding a solution to my script not outputting anything while calling flush and ob_flush, I thought of trying to tell PHP to call:
session_write_close();
before starting echo'ing. It worked like a charm. I couldn't find any references to this, so I hope this note will help someone in the future.
02-Feb-2005 05:25
On Windows xampp 1.3 with php 4.3.4 is use this functions
to force a flush.
<?php
function dummyErrorHandler ($errno, $errstr, $errfile, $errline) {
}
function forceFlush() {
ob_start();
ob_end_clean();
flush();
set_error_handler("dummyErrorHandler");
ob_end_flush();
restore_error_handler();
}
?>
ob_end_flush generates a warning, which is supressed, using the dummy-errorhander. You could also use @, but then nusphere will also print the warning.
11-Nov-2004 09:26
This code does not work as expected
<pre>
<?php
echo "Test1\n";
flush();
sleep(3);
echo "Test2\n";
?>
</pre>
It should print Test1, wait 3 seconds then print Test2 but actually it prints everything at the end.
It seems PHP is doing output buffering on its own, here is the way to make it work :
<pre>
<?php
ob_end_flush();
echo "Test1\n";
flush();
sleep(3);
echo "Test2\n";
?>
</pre>
You don't really need to repeat some "fake" text to fill the buffer in order to make this effect.
06-Oct-2004 08:57
Something about the Linux version of Firefox makes flush() not work. Not sure if this is specifically a Firefox problem, or something about the way Linux handles HTTP streams, but nothing gets rendered until the HTTP stream is closed.
Interestingly, flush() works fine running IE on Linux under Wine.
25-Feb-2004 02:25
Netscape will flush the output as expected at the point it is called from within your script. IE, however, needs a boost.
IE seems to have a condition where it will flush data when it hits an end (</table>) tag AND has at least 256 chars of data.
So, pad your output with necessary spaces, wrap your progressing data around open (<table>) and end (</table>) tags, and then call flush() so that one script will work for Netscape as well.
TESTING ENVIRONMENT
IE: Ver/6.0.2800
Netscape: Ver/7.1
PHP: Ver/4.3.4
Apache: Ver/1.3.27
24-Jan-2004 08:46
If you are having trouble makeing flush(); or ob_flush(); work the way you want, try both of them.
Using PHP 4.3.3RC1 there was no effect using flush() or ob_flush(), however a combination of both gave me perfect results.
Example:
<?
echo str_repeat(" ", 256);
$i = 100;
while($i > 0)
{
echo $i." bottle".($i != 1 ? 's' : '')." of beer on the wall, ".$i." bottle".($i != 1 ? 's' : '')." of beer. Take one down and pass it around, ".(--$i)." bottle".($i != 1 ? 's' : '')." of beer on the wall<br>\n";
flush();
ob_flush();
usleep(50000);
}
?>
This could be the result of a server-issue - maybe you are using a public server that has OB enabled by default.
21-Jan-2004 05:25
Note to my last posting:
Since version 4.2.0 you can use ob_flush() instead. This works fine with sessions and cookies disabled.
30-Oct-2003 12:22
in order to display in HTML pages something like a "progress bar" or if you want to force the web server to flush output to the browser, or the browser to flush as well, you can print a long enough "dummy" string to make the output buffer grow, as you probably know, like:
print "[";
for($i = 0; $i < 100; $i++){
$spaces.=" ";
} // for
//and then
for($i = 0; $i < 10; $i++){
for($ii = 0; $ii < 200000; $ii++){
//do something slow here
} // for
print "$spaces|";
flush();
} // for
print "]";
/*
but this somethin may be not really what you expect in
a progress bar, as it prints spaces (although rendered as single by the browser) between the bar units..
you can solve this using
$spaces.="<!-- bufferme -->";
/*
print "[";
for($i = 0; $i < 100; $i++){
$spaces.="<!-- bufferme -->";
} // for
//and then
for($i = 0; $i < 10; $i++){
for($ii = 0; $ii < 200000; $ii++){
//do something slow here
} // for
print "$spaces|";
flush();
} // for
print "]";
//which looks nice as a progress bar..
01-Oct-2003 11:40
Regarding Apache2
flush() will produce the same results as ob_flush() when output buffering is involved.
24-Jul-2003 05:52
This may not be obvious from the previous posts.
You must flush all HTML up to and including the <body> tag (<head>, <meta>, etc.), or the browser won't respond. This would have the effect of "blanking" the page while waiting for the script to complete. This is in addition to the other tips posted.
Most users expect something immediate to happen when they click on a link. "Blanking" the page is often times better for those not accustomed to keeping an eye on their browser's progress bar.