5

I have an object for tasks and on __deconstruct(), it's meant to run some of the lengthier cleanup tasks after the rest of the page has already loaded. Unfortunately, it buffers the output and won't send it until after the tasks are finished (nothing is printed in the tasks).

I've read through http://www.php.net/flush and tried all the suggestions there. Obviously I've tried disabling output_buffering in php.ini. I've disabled deflate_module, zlib compression is off, don't have mod_gzip. Calling flush() or ob_flush() has no effect, nor does enabling implicit_flush.

I'm just running XAMPP (currently apache 2.2.17, php 5.3.4) under Windows Server 2008 R2. PHP is being run as a module.

And yes, I could set up some little AJAX hack to run the task manager or even set up a scheduled task to run this specific task, but output buffering has been an issue elsewhere, too. Would just like it to be gone sometimes.

From a similar thread, someone suggested seeing what the following would do:

<?php
while (TRUE)
{
    echo 'x';
    flush();
    sleep(1);
}
?>

As expected, the page displays nothing until the maximum execution time is reached, at which point it flushes the buffer.

This has become extremely frustrating. Anyone have any ideas what could still be causing it to buffer?

Apropos
  • 508
  • 5
  • 15
  • Can you confirm that the output is still getting buffered vs. the browser just not displaying anything (e.g., IE won't display anything until it receives some number of bytes)? –  Mar 15 '12 at 20:45
  • does this function http://php.net/manual/en/function.ob-get-level.php return 0? – dqhendricks Mar 15 '12 at 20:47
  • can you try this if it helps http://in3.php.net/manual/en/function.ob-end-flush.php – Saket Patel Mar 15 '12 at 20:54
  • I had tried multiple browsers, so I was figuring that wasn't the problem. Upon actually testing it, of course, it turns out it was. And ob_get_level() returns 0, as it wasn't the issue. – Apropos Mar 15 '12 at 20:56

2 Answers2

4

You're only sending a small amount of data. Browsers have their own buffer, which can be based on a number of bytes, by which elements have been received, or by something else.

In short, there is nothing you can do about this. The buffering is happening client-side, not server-side. You could try sending more data before your xs.

You can prove this by packet sniffing the connection between the server and the browser, with Wireshark or similar.

Brad
  • 159,648
  • 54
  • 349
  • 530
  • Well, I was going to say that I was sending a fair bit of data before, but upon changing it to for($i=0;$i<10000;$i++){echo 'x
    ';sleep(1)}, it outputs just fine. I guess the only workaround would be sending more data to force the browser to display it. Might not be ideal. Thanks, though. I kept going through my scripts and configs and it was driving me insane.
    – Apropos Mar 15 '12 at 20:55
  • IE is known for this. I tricked IE by sending around 1000 spaces just before flushing. Because HTML conflates spaces it does not matter. – nalply Aug 03 '12 at 21:49
4

hmmm, interesting grabbed a snip of code I have used else where and it works as expected...

https://stackoverflow.com/a/9728519/632951

<?php
echo str_repeat('fillerbytes',20*1024/strlen('fillerbytes'));
echo '<body style="font-size:6px;font-family:arial;">';
echo str_repeat('<br>',2);
    for($i=1; $i<=5000; $i++){
        echo $i . ' ';
        ob_flush();
        flush();
        usleep(2000); // 2 ms each = 10s total
    }
?>

Watch my server count to 5000 http://atwebresults.com/texttest/new.php

(Doesn't work on some free hosts like freehostingeu.com.)

Pacerier
  • 86,231
  • 106
  • 366
  • 634
Tim Wickstrom
  • 5,476
  • 3
  • 25
  • 33
  • Yes, this works. Unfortunately, it's only because it's sending far more data than I wanted to send. Changing the time between iterations to 1s instead of .001s causes the unwanted behavior to return. – Apropos Sep 17 '12 at 21:49
  • This make my day. I think it works because of the use of ob_flush(); instead of flush(); – Alrik Nov 27 '12 at 17:26
  • It's because of the amount of data sent, not ob_flush(). The original example fails even when adding ob_flush(), or this one fails when changing the time between iterations to 1s instead of a thousandth of a second like it currently is. – Apropos Dec 02 '12 at 17:54
  • @TimWick, **Note that streaming to the end user only works if they are no intermediaries buffering the response.** Also see https://archive.is/e1jB#selection-1725.262-1725.307 – Pacerier Oct 27 '17 at 17:42
  • @TimWickstrom, Which hosting company do you use? – Pacerier Oct 27 '17 at 17:43