PHP Flush que funciona... incluso en Nginx
(8)
¿Es posible hacer eco cada vez que se ejecuta el ciclo? Por ejemplo:
foreach(range(1,9) as $n){
echo $n."/n";
sleep(1);
}
En lugar de imprimir todo cuando termina el ciclo, me gustaría verlo imprimiendo cada resultado por vez.
Debes limpiar el búfer de php en el navegador
foreach(range(1,9) as $n){
echo $n."/n";
flush();
sleep(1);
}
Descubrí que puedes configurar:
header("Content-Encoding:identity");
en su script php para desactivar nginx gzipping sin tener que modificar el nginx.conf
La forma más fácil de eliminar el almacenamiento en búfer de nginx es emitiendo un encabezado:
header(''X-Accel-Buffering: no'');
Esto elimina tanto proxy_buffering
como (si tiene nginx> = 1.5.6), fastcgi_buffering
. El bit fastcgi es crucial si estás usando php-fpm. El encabezado también es mucho más conveniente de hacer según sea necesario.
Documentos sobre X-Accel-Buffering Docs en fastcgi_buffering
No quería tener que apagar gzip para todo el servidor o un directorio completo, solo para algunos scripts, en algunos casos específicos.
Todo lo que necesitas es esto antes de que cualquier cosa se repita:
header(''Content-Encoding: none;'');
Luego haz el color como siempre:
ob_end_flush();
flush();
Nginx parece darse cuenta de que la codificación se ha desactivado y no gzip.
Puede lograr esto descargando el búfer de salida en el medio del bucle.
Ejemplo:
ob_start();
foreach(range(1,9) as $n){
echo $n."/n";
ob_flush();
flush();
sleep(1);
}
Tenga en cuenta que su configuración php.ini puede afectar si esto funcionará o no si tiene activada la compresión zlib
SOLUCIÓN FINAL
Entonces eso es lo que descubrí:
Flush no funcionaría bajo mod_gzip de Apache o gzip de Nginx porque, lógicamente, está comprimiendo gzip el contenido, y para hacerlo debe almacenar el contenido para gzip. Cualquier tipo de servidor web gzipping afectaría esto. En resumen, en el lado del servidor, tenemos que desactivar gzip y disminuir el tamaño del búfer fastcgi. Asi que:
En php.ini:
. output_buffering = Off
. zlib.output_compression = desactivado
En nginx.conf:
. gzip apagado;
. proxy_buffering off;
También tenga estas líneas a mano, especialmente si no tiene acceso a php.ini:
@ini_set (''zlib.output_compression'', 0);
@ini_set (''implicit_flush'', 1);
@ob_end_clean ();
set_time_limit (0);
Por último, si lo tiene, comente el siguiente código:
ob_start (''ob_gzhandler'');
ob_flush ();
Código de prueba de PHP:
ob_implicit_flush(1);
for($i=0; $i<10; $i++){
echo $i;
//this is for the buffer achieve the minimum size in order to flush data
echo str_repeat('' '',1024*64);
sleep(1);
}
Relacionado:
Solución fácil en el servidor nginx:
fastcgi_keep_conn on; # < solution
proxy_buffering off;
gzip off;
Tuve un problema gzip proveniente de mi motor php-fpm. este código es el único que funciona para mí:
function myEchoFlush_init() {
ini_set(''zlib.output_compression'', 0);
ini_set(''output_buffering'', ''Off'');
ini_set(''output_handler'', '''');
ini_set(''implicit_flush'', 1);
ob_implicit_flush(1);
ob_end_clean();
header(''Content-Encoding: none;'');
}
function myEchoFlush($str) {
echo $str . str_repeat('' '', ini_get(''output_buffering'') * 4) . "<br>/n";
}
Esta es mi función de prueba: comprueba max_execution_time:
public function timeOut($time = 1, $max = 0) {
myEchoFlush_init();
if ($max) ini_set(''max_execution_time'', $max);
myEchoFlush("Starting infinite loop for $time seconds. It shouldn''t exceed : " . (ini_get(''max_execution_time'')));
$start = microtime(true);
$lastTick = 1;
while (true) {
$tick = ceil(microtime(true) - $start);
if ($tick > $lastTick) {
myEchoFlush(microtime(true) - $start);
$lastTick = $tick;
}
if ($tick > $time) break;
}
echo "OK";
}