ob_implicit_flush(), flush(), ob_flush() - not working on remote server
Asked Answered
R

4

5

If I load this script in chrome from my local server on XAMPP:

header("Content-Type:text/plain");

set_time_limit(0);

$max = 40;
for ($i = 0; $i < $max; $i++) {
    $response = array(  'server time: ' . date("h:i:s", time()), 'progress' => round($i/$max*100));
    echo json_encode($response);
    ob_flush();
    flush();
    sleep(1);
}
ob_clean();

It works as you would expect, every second the page displays a new response. However, when I upload it to my remote server (running the same version of php), it waits until the entire script finishes before it displays the output. On very long scripts, it updates the output every 30-60 seconds or so.

As the title suggests, I've tried using all the different flush functions, but nothing works. There is likely some difference in the php.ini of my local server and my remote server, but I don't know what.

Please help.

---EDIT---

I've been doing some more testing. I've noticed that exactly it only updates every 4096 bytes, which happens to be what my remote server's php ini value for 'output_buffering' is. However, for some reason, if I change output_buffering to '1' or 'off', nothing changes. It still only updates every 4096 bytes.

I'm testing the 2 identical scripts on different servers on the same browser.

Reel answered 12/9, 2015 at 12:1 Comment(4)
The doc page of flush() is full of disclaimers of why this may or may not work. It could be something you can't even fix.Demand
It's more likely to be Apache buffering the output..... this is not an effective mechanism to use for a timerPipsqueak
I've been doing some more testing. I've noticed that exactly it only updates every 4096 bytes, which happens to be what my remote server's php ini value for 'output_buffering' is. However, for some reason, if I change output_buffering to '1' or 'off', nothing changes. It still only updates every 4096 bytes.Reel
I worked it out. My remote server uses nginx, and all I needed to do was put: header("X-Accel-Buffering: no"); at the top of the php script.Reel
R
14

I didn't take into account nginx, which has it's own output buffer.

I simply added 'header("X-Accel-Buffering: no");' to the top of the php script and it all works fine now.

Reel answered 22/9, 2015 at 17:57 Comment(2)
Works perfectly! - PHP 7.2 FPMIndeterminism
Does that also work for apache?Marleah
A
12

For me adding header('Content-Encoding: none'); did the trick. This is needed when using PHP-FPM.

Amadeo answered 29/9, 2015 at 12:5 Comment(1)
This has worked for me on a shared hosting (hostgator) after months without any solution. thxChicory
I
0

This works fine in Apache + PHP

header('Content-Encoding: none');
ob_implicit_flush(1);

echo "<br>PROCESSING bla bla bla";

Optionally you can add the following line (after every small piece of data) if you want to throw out really small chunks too.

echo str_repeat(' ',1024*64);
Ivories answered 18/1, 2023 at 13:46 Comment(0)
B
-2

Before you need use ob_start() and ob_end_clean(). And add header Content-Length or Transfer-Encoding: chunked. And check if «implicit_flush» is On in your php.ini

Add padding for response. Check this code:

<?php

set_time_limit(0);
ob_start();

header('Content-Type: text/plain');

define("PADDING", 16);

//+padding
for($i=0;$i<PADDING;$i++){
    //64 spaces (1 block)
    echo str_repeat(' ', 64);
}

$max = 40;
for ($i = 0; $i < $max; $i++) {
    $response = array(  'server time: ' . date("h:i:s", time()), 'progress' => round($i/$max*100));
    echo json_encode($response);
    ob_flush();
    flush();
    sleep(1);
}
ob_end_clean();

?>
Burner answered 12/9, 2015 at 12:18 Comment(2)
Tried. Still the same.Reel
You local server run with apache and remote server nginx + apache? I think you have to look configure nginxBurner

© 2022 - 2024 — McMap. All rights reserved.