12

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();
}
Kavin Anbazhagan
  • 208
  • 1
  • 2
  • 15
  • 5
    Start by removing those `@`s, you'll get way better error messages if something breaks. Moreover, 'it does not work' is *never* a good error description. What do you expect your code to do and what does it do instead? This might as well be a caching issue. – Marcel Korpel May 14 '11 at 11:53
  • Tried it but no change in result... – Kavin Anbazhagan May 14 '11 at 12:00
  • 3
    No, removing `@`s will not change the result (you know what they do, don't you? If not, why did you put them in in the first place?). Again, what do you expect your code to do and what does it do instead? This might as well be a caching issue. – Marcel Korpel May 14 '11 at 12:01
  • I just want to echo text intermittently while the script is executing. I do know what @ is for but in this case am not expecting any errors for sure. – Kavin Anbazhagan May 14 '11 at 12:25
  • 7
    If you're not expecting any errors, why do need `@`s? – seriousdev May 14 '11 at 12:51

5 Answers5

10

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.

meetar
  • 7,443
  • 8
  • 42
  • 73
4

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();
    }
    
KingCrunch
  • 128,817
  • 21
  • 151
  • 173
  • 1
    And to add: you will not see anything if the only thing you output is an HTML comment. If I try outputting something visual, I do see this when flushing. – Marcel Korpel May 14 '11 at 13:39
  • @Marcel: Yes, of course. I always look at the source, so I missed the point, that many forget, that html-comments are not display within the browser window ;) – KingCrunch May 14 '11 at 13:46
  • For me, the trick was to use `ob_flush()` alongside `flush()`. – David Refoua Nov 16 '16 at 15:06
3

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()
Denis de Bernardy
  • 75,850
  • 13
  • 131
  • 154
2

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.

SimonSimCity
  • 6,415
  • 3
  • 39
  • 52
  • 1
    "If you have gzip enabled the whole response from the server will be buffered" led me [here](https://stackoverflow.com/a/21138598/924299). – showdev Mar 24 '21 at 23:45
1

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

enter image description here

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.

Community
  • 1
  • 1
Jayapal Chandran
  • 10,600
  • 14
  • 66
  • 91