I have a time-consuming php script, so I'd like to give the user some feedback. Simplified it to get to the core problem. This script works perfectly fine in Firefox (flushing the output instantly), but Safari waits until all the content is generated. Why? And how could I fix that?
<?php
ini_set('max_execution_time', 0);
header('Content-Encoding: none;');
header('Content-type: text/html; charset=utf-8');
$j = 8;
$k = pow(2, 10);
echo "One moment please...".str_pad('', $k)."<br />\n<br />\n";
flush();
$i = 0;
while ($i < $j) {
$i++;
echo "Test ".$i.str_pad('',$k)."<br />\n";
flush();
sleep(1);
}
?>
And by the way: Chrome won't load this page at all, it gives me ERR_CONTENT_DECODING_FAILED
.
Furthermore I tried to put
<IfModule mod_env.c>
SetEnv no-gzip 1
</IfModule>
in .htaccess but no luck. Also tried SetEnv no-gzip dont-vary
. Any clues how to get Safari (and Chrome) do the same as Firefox?
I read everything on php.net about flush()
, ob_flush()
, ob_start()
, etc. and I read almost every question about flush + all comments on Stackoverflow from the past 20+ years.
I tried to add ini_set('output_buffering', 'On');
or ini_set('output_buffering', 'Off');
, added ob_start(null, 4096);
, ini_set('zlib.output_compression', 'Off');
, header('Cache-Control: no-cache');
, header('X-Content-Type-Options: nosniff');
and/or header('X-Accel-Buffering: no');
. I put @ob_flush();
before or after my flush();
, tried to raise the value in str_pad
up to 2^16 (65,536) but nothing helped.
Unfortunately I don't seem to have any control over the Apache server at my hosting provider (which runs PHP 8.1 with FastCGI). Since it works on Firefox I must have done something right, I thought.
Edit:
ob_start("ob_gzhandler")
is intended to be used as a callback function for ob_start() to help facilitate sending gz-encoded data to web browsers that support compressed web pages. source
<?php
ini_set('max_execution_time', 0);
header('Content-Encoding: none;');
header('Content-type: text/html; charset=utf-8');
ob_start("ob_gzhandler");
$j = 8;
$k = pow(2, 10);
echo "One moment please...".str_pad('', $k)."<br />\n<br />\n";
$i = 0;
while ($i < $j) {
$i++;
echo "Test ".$i.str_pad('',$k)."<br />\n";
ob_flush();
sleep(1);
}
?>
Outputs (on Chrome):
One moment please...
Test 1 Test 2 Test 3 Test 4 Test 5 Test 6 Test 7 Test 8