2011-01-16 19 views
11
<?php 
for($i=0;$i<20;$i++) 
{ 
    echo 'printing...<br />'; 
    ob_flush(); 
    flush(); 

    usleep(300000); 
} 

?> 

URL que contiene el código: http://domainsoutlook.com/sandbox/delayed.phpphp descarga no trabaja

Tengo un servidor dedicado para que pueda realizar los cambios. Estoy ejecutando apache y nginx como el servidor proxy.

+4

Apache _AND_ nginx? Creo que nginx sería suficiente. – jwueller

+0

¿Qué esperas que pase? –

+0

Debe 'ob_flush()' venir después de 'flush()', y también usted el ciclo. Necesito iniciar un buffer de salida con 'ob_start()' antes del loop – RobertPitt

Respuesta

8

Está utilizando ob_flush sin ob_start, por lo que no hay nada que lavar.

También depende del servidor web y del proxy y su configuración.

Debe desactivar el almacenamiento en búfer de Nginx (añadir "proxy_buffering fuera;" al archivo de configuración y reinicie Nginx)

Además, verifique si su php.ini contiene "output_buffering = Off" y "zlib.output_compression = Off ".

+0

donde normalmente está el archivo de configuración nginx donde puedo agregar estos valores –

+0

Debe ser '/ etc/nginx.conf' – schnaader

+0

doy esta línea para nginx en el módulo core http –

31

Así que eso es lo que descubrí:

Flush no funcionaría bajo mod_gzip de Apache o gzip de Nginx, ya que, lógicamente, se gzipping el contenido, y para hacer eso tiene que amortiguar el contenido de 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. Por lo tanto:

  • En php.ini:

    . output_buffering = Off

    . zlib.output_compression = Off

  • En nginx.conf:

    . gzip apagado;

    . proxy_buffering off;

tienen también estas líneas a mano, especialmente si usted no tiene acceso a php.ini:

  • @ini_set ('zlib.output_compression ', 0);

  • @ini_set ('implicit_flush', 1);

  • @ob_end_clean();

  • set_time_limit (0);

pasado, si lo tiene, coment el código de abajo:

  • ob_start ('ob_gzhandler');

  • ob_flush();

PHP código de prueba:

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); 
} 
+7

Lo último que "me resuena 64k ** sin sentido ** espacio en blanco" me sirvió. Gracias, Roger. – humanityANDpeace

+0

. proxy_buffering off; fue el problema en mi configuración. ¡Gracias! – Noam

+0

He hecho todo esto pero no estoy trabajando en live centos7 apache con php 5.5.Trabajando sin problemas localmente incluso con output_buffering = 4096 – Azghanvi

0

Mientras leo, parece un pb muy difícil de resolver, y la única manera (sucio) que he encontrado es escribir algo inútil de salida para llenar los ≠ buffers. - sin ssl - sin output_buffering, se necesita color, los búferes nginx se pueden bajar hasta que el tamaño del encabezado php - con output_buffering, ob_flush deba agregarse para tener el mismo comportamiento que el anterior - con ssl, hay otro buffer para SSL y NGX_SSL_BUFSIZE se fija en la compilación nginx

Aquí está mi archivo test.php (llamarlo con? size = ... para cambiar la escritura de espacio en el bucle)

<!DOCTYPE html> 
<html> 
<head></head> 
<body> 
<?php 
$vars = array('output_buffering', 'zlib.output_compression'); 
print('<p>'); 
foreach ($vars as $var) { 
    print("$var : "); 
    var_dump(ini_get($var)); 
    print('<br />'); 
} 
print("ob_get_level() : " .ob_get_level()); 
print('</p>'); 
if (ob_get_level()) { 
    $bytes = ob_get_length(); 
    ob_flush(); 
} 

$nb_iterations = !empty($_GET['nb']) ? max(2, (int) $_GET['nb']) : 5; 
$size = !empty($_GET['size']) ? $_GET['size'] : 0; 

for ($i = 1; $i < $nb_iterations; $i++) { 
    sleep(1); 
    print(str_repeat(' ', 1024 * $size)); 
    print("<p>wait $i s</p>"); 
    if (ob_get_level()) { 
    $bytes += ob_get_length(); 
    print($bytes + strlen($bytes)); 
    ob_flush(); // this is working, results aren't depending on output_buffering value 
    } 
    flush(); // this is needed 
} 
?> 
</body> 
</html> 

y la conf más baja que pueda el conjunto es

location ~ ^/test.php$ { 
    gzip off; 
    fastcgi_pass unix:/var/run/php5-fpm/ssl.socket; 
    fastcgi_param QUERY_STRING   $query_string; 
    fastcgi_param REQUEST_METHOD   $request_method; 
    fastcgi_param SCRIPT_FILENAME   $request_filename; 
    # if too low => upstream sent too big header while reading response header from upstream 
    fastcgi_buffer_size 128; 
    fastcgi_buffers 2 128; 
    fastcgi_busy_buffers_size 128; 
} 
10

Archivo principal de php;

<?php 
header('Content-Type: text/HTML; charset=utf-8'); 
header('Content-Encoding: none; ');//disable apache compressed 
session_start(); 
ob_end_flush(); 
ob_start(); 
set_time_limit(0); 
error_reporting(0); 

..... bla bla 

for(each)........ 
{ 
    bla bla.. 
    echo "<br>>>>".$i."<<<br>"; 
    ob_flush(); 
    flush(); //ie working must 

} 
?> 

que está funcionando ..

+1

Content-Encoding fue lo que funcionó para mí en nginx, sin tener que desactivarlo para todo el servidor. Gracias Emin! – Redzarf

+1

El ajuste 'Content-Encoding' finalmente hizo que el enrojecimiento funcionara en Firefox, pero de alguna manera Chrome aún esperaba una respuesta comprimida, por lo que arrojó un error' ERR_CONTENT_DECODING_FAILED'. – skerit

0

En php.ini:

output_buffering = Off zlib.output_compression = Off

En nginx.conf:

fastcgi_keep_conn sucesivamente; # < solución

proxy_buffering off; gzip desactivado;

1

Otra causa posible es mod_security. Parece que tiene sus propios buffers. Así que si usted lo está utilizando, tendrá que establecer:

SecResponseBodyAccess Off 

especie de solución sucia, pero hasta el momento que la única manera que tengo que trabajar.

1

Tiene que llenar el búfer, para que pueda ser enjuagado al navegador.Utilice esta después de eco

echo str_pad('',4096)."\n"; 

Código completo:

<?php 
    if (ob_get_level() == 0) ob_start(); 

    for($i=0 ; $i<20 ; $i++) { 
     echo 'printing...<br />'; 
     echo str_pad('',4096)."\n"; 

     ob_flush(); 
     flush(); 

     usleep(300000); 
    } 
    ob_end_flush(); 
?> 
0

me he dado cuenta de que los navegadores reaccionan de manera diferente. Chrome, por ejemplo, retiene la entrada para siempre y no parece importarle mostrarla antes. Como era de esperar, Firefox mostrará la entrada antes, si se aplican las sugerencias anteriores (aportadas por otros stackoverflowers), entonces intente con Firefox.

1

Solo quería agregar a la respuesta de Roger.

Si está usando FastCGI php5-fpm módulo dentro Apache 2 también debe asegurarse de que está agregando argumento

-flush

en la configuración de Apache 2, es decir

<IfModule mod_fastcgi.c> 
... 
     FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -flush -socket /tmp/php5-fpm.sock -idle-timeout 480 -pass-header Authorization 
</IfModule> 
0

Pude descargar solo de esta forma, agregando session_write_close();

if (ob_get_level() == 0) 
{ 
    if(!ob_start("ob_gzhandler"))ob_start(); 
}    
echo ('bla bla bla'); 

$ans=ob_get_contents(); 
ob_end_clean(); 

header('Connection: close'); 
header('Content-Length: '.strlen($ans)); 
header('Status: 200'); 

echo $ans; 

session_write_close(); 
ob_flush(); 
flush(); 
0

Compruebe su API de servidor con

echo phpinfo(); 

Si usted encontró su API de servidor

Server API : CGI/FastCGI 

en CentOS a continuación, añadir esta línea en "/etc/httpd/conf.d/fcgid .conf "

OutputBufferSize 0 

Para probar, reinicie su Apache se rver y tratar a continuación el código

ob_start(); 
for($i = 0; $i < 10; $i ++) { 
    echo $i; 
    echo '<br />'; 
    flush(); 
    ob_flush(); 
    sleep(1); 
} 
0
if(!ob_get_level()) ob_start(); 
echo json_encode(array('valid'=>true,'msg'=>'Flush occured.')); 
$size = ob_get_length(); 
header("Content-Type: application/json"); 
// Set the content length of the response. 
header("Content-Length: {$size}"); 
//Close the connection if you want to. 
header("Connection: close"); 
// Flush all output. 
ob_end_flush(); 
ob_flush(); 
flush(); 
// Close current session (if it exists). 
if(session_id()) session_write_close(); 
+0

¿Podría explicar este código y cómo responde esto a la pregunta? Gracias. – iehrlich