I stumbled upon this function which promised to work across IE, FF & Chrome. But it does not work in Chrome. Is there a work around?
function buffer_flush(){
echo str_pad('', 512);
echo '<!-- -->';
if(ob_get_length()){
@ob_flush();
@flush();
@ob_end_flush();
}
@ob_start();
}
Here's how I got flush() working in a while loop in Chrome 12.0.742.122 with PHP 5.3.6:
echo("<html><body>");
while(1) {
echo(str_pad($my_string_var,2048," "));
@ob_flush();
flush();
}
Using a lesser str_pad value worked too, but it would take a bit longer for the first output to appear. If any of the other lines were missing, nothing would appear.
The "@" isn't strictly necessary, but it prevents the log from filling up with "nothing in the buffer" notices.
And of course if you have a pre-existing page, just make sure the <html>
and <body>
tags are in there; I was writing a page from scratch.
With flush()
/ob_flush()
you only send the output to the browser, but its still up to the browser, when it displays it. I assume, that chrome just waits, until it has enough data received to display a "useful" page, instead of some fragments.
Some suggestions anyway:
- Avoid using
@
(especially if you don't know exactly, what it does)
If you don't call ob_end_*()
, you don't need to call ob_start()
again. Its inefficient
function buffer_flush(){
echo '<!-- -->'; // ?
ob_flush();
flush();
}
Some browsers (IE6 at the very least, and possibly chrome) require a certain amount of "useful" characters (i.e. not spaces) before outputting anything. In the case of IE6, it even is the compressed data's size that needs to be pushed.
function force_flush() {
echo "\n\n<!-- Deal with browser-related buffering by sending some incompressible strings -->\n\n";
for ( $i = 0; $i < 5; $i++ )
echo "<!-- abcdefghijklmnopqrstuvwxyz1234567890aabbccddeeffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz11223344556677889900abacbcbdcdcededfefegfgfhghgihihjijikjkjlklkmlmlnmnmononpopoqpqprqrqsrsrtstsubcbcdcdedefefgfabcadefbghicjkldmnoepqrfstugvwxhyz1i234j567k890laabmbccnddeoeffpgghqhiirjjksklltmmnunoovppqwqrrxsstytuuzvvw0wxx1yyz2z113223434455666777889890091abc2def3ghi4jkl5mno6pqr7stu8vwx9yz11aab2bcc3dd4ee5ff6gg7hh8ii9j0jk1kl2lmm3nnoo4p5pq6qrr7ss8tt9uuvv0wwx1x2yyzz13aba4cbcb5dcdc6dedfef8egf9gfh0ghg1ihi2hji3jik4jkj5lkl6kml7mln8mnm9ono -->\n\n";
while ( ob_get_level() )
ob_end_flush();
@ob_flush();
@flush();
} # force_flush()
There are several components that can have impact on this issue.
Read carefully through the documentation of this function:
http://www.php.net/manual/en/function.flush.php
One solution I had was using Apache2 with mod-php (not as fcgi but as native apache-module) and Chromium. The result came immediately and the script was still running and sending more results.
After typing the following two code-lines every echo-command will immediately push the text to the whatever-PHP-backend:
ob_implicit_flush(1);
@ob_end_flush(); // set an end to the php-output-buffer!
But this php backend can have its own buffer. For example I run nginx as webserver and php is used by the fast-cgi module. Nginx itself has its own buffer ... and so on.
The Browser also can buffer the request. But as I experience Chromium (or Google Chrome) has a verry small or no buffer.
Please read the documentation of every function I mentioned to understand what they really do - but specially the documentation of flush().
Personal hint: Do not put extra characters into the output-buffer but read and understand the configuration of your server.
EDIT:
If you have gzip enabled the whole response from the server will be buffered.
I found that a content type header really makes it work in chrome after few trial and errors.
But i don't know why chrome does not flush otherwise.
after searching for more answers i read that chrome flushes as you expect only when a valid content type is set. fine.
Here is the code i experimented.
<?php
header('Content-Type: text/html; charset=UTF-8');
echo 'starting...';
flush();
echo 'to sleep...';
flush();
sleep(5);
echo 'awake';
if i do not include the content type header i get like the following in one shot after 5 seconds. so what we expect did not work.
starting...to sleep...awake is displayed and the script terminates.
where as when i gave the content type like the above with the subtype(charset) then
starting...to sleep... is displayed immediately and then after 5 seconds awake is displayed.
i am just blindly assuming that with respect to the content type header chrome shows the output.
Besides when i gave 'Content-Type: text/plain' or 'Content-Type: text/html' it did not work. it worked only with the subtype 'charset=[sometexthere]'.
were as application/json worked. and i did not experiment with more mimes.
The reason i am here is
i wanted to use readystate 3 in ajax response. it works fine except chrome and safari. since chrome is using webkit it is the same in both i think.
in other browsers including IE the flushing is working as expected and also the readystate=3 but in chrome and safari i just used the above workaround.
here is the screenshot of the readystate - responsetext from the above php script
in the image there a two sets of response the first one with readystate 3 and responsetext as empty when content type is not used.
in the second response you can see ready state 3 has responsetext with the expected output. this is when content type is used.
so... Chrome only knows.
when used str_pad
When you use string padding you can get more expected result. i tried with 1024 as the above answers suggested but only with content type set.
if padding is used and no content type is set then it did not work.
and
i had raised a question similar to this and i am going to add my own answer by linking this answer to that and back to back... so that it will be easy for users to get more details. hhmmm.