2011-08-24 6 views
6

Abbiamo utilizzato php flush per "vuoto" una pagina immediatamente non appena si fa clic e anche per inviare la navigazione e i componenti principali della pagina in modo che una pagina venga visualizzata quasi istantaneamente , anche se a volte il contenuto potrebbe richiedere molto tempo per essere caricato.PHP flush stopped flushing in IIS7.5

Questo ha funzionato molto bene.

Recentemente abbiamo eseguito l'aggiornamento da IIS 7.0 a 7.5 e ora lo svuotamento non funziona. Durante l'analisi del problema, abbiamo disattivato la compressione per file sia statici che dinamici. Abbiamo anche disattivato il caching dell'output.

Abbiamo anche disattivato la compressione di zlib e disattivato il buffering in php.ini.

Al fine di verificare il problema che abbiamo il seguente script

@ini_set("output_buffering", "Off"); 
@ini_set('implicit_flush', 1); 
@ini_set('zlib.output_compression', 0); 

ob_start(); 

echo "starting...<br/>\n"; 
for($i = 0; $i < 5; $i++) { 
    print "$i<br/>\n"; 
    ob_end_flush(); 
    ob_flush(); 
    flush(); 
    ob_start(); 
    sleep(2); 
} 
print "DONE!<br/>\n"; 

Il browser mostra solo lo stato di caricamento (qualunque cosa sia in qualsiasi browser, in IE Sembra una GIF animata Ajax, in Firefox la la scheda indicherà "Connessione in corso ...") per 10 secondi, quindi improvvisamente verrà visualizzata l'intera uscita.

Abbiamo provato varie combinazioni di flush, ob_flush e ob_end_flush basate su domande simili su questo sito. Nessuno di loro funziona. C'è un modo per rendere IIS/PHP scaricare i dati?

risposta

7

È necessario impostare il valore ResponseBufferLimit del gestore desiderata per un numero sufficiente di realtà a livello basso. Vi consiglio di usare 0 poiché impedisce a IIS di fare qualsiasi cosa se non di passare ciò che viene inviato dallo script PHP. È possibile utilizzare la seguente riga di comando per impostare la ResponseBufferLimit a 0 per il gestore php (basta cambiare “NAME” per il nome del gestore che si desidera aggiornare ad es PHP53_via_FastCGI):

appcmd.exe set config /section:handlers "/[name='NAME'].ResponseBufferLimit:0" 

In alternativa, è possibile modificare applicationHost.config direttamente e aggiungi un attributo ResponseBufferLimit all'elemento XML.

3

Quello che faccio è che io uso la seguente funzione:

function flush_buffers(){ 
    ob_end_flush(); 
    ob_flush(); 
    flush(); 
    ob_start(); 
} 

Così nel codice:

ob_start(); 
flush_buffers(); 

echo "starting...<br/>\n"; 
for($i = 0; $i < 5; $i++) { 
    print "$i<br/>\n"; 
    flush_buffers(); 
    sleep(2); 
} 

Si dovrebbe funzionare senza problemi :-)


Ecco codice funzionante (con il set corretto Content-Type):
DEMO
CODE

<?php 
header("Content-Type: text/html; charset=utf-8"); 
function flush_buffers(){ 
    ob_end_flush(); 
    ob_flush(); 
    flush(); 
    ob_start(); 
} 

ob_start(); 
flush_buffers(); 
echo "starting...<br/>\n"; 
for($i = 0; $i < 60; $i++) { 
    flush_buffers(); 
    print "$i<br/>\n"; 
    flush_buffers(); 
    sleep(2); 
} 

flush_buffers(); 

print "DONE!<br/>\n"; 
?> 
+0

Questo ha funzionato. Separandolo pezzo per pezzo per vedere quale è la chiave ... –

+0

@Jeff, la demo dovrebbe aiutare un po ':-) – Neal

+1

Sembra che la chiave sia il tipo di contenuto: text/html; charset = utf-8. Anche l'aggiunta come intestazione funziona. In particolare sembra che il set di caratteri = utf-8 sia ciò che lo fa funzionare. –

1

E 'fino al server web sia che si decida di naggle il contenuto o inviarlo tramite codifica Chunked. Quindi, anche se PHP può chiedere al server di inviare dati al client, non può forzare il server a utilizzare la codifica Chunked.

This article suggerisce di impostare esplicitamente la codifica del trasferimento per IIS (vedere il bit su ISAPI) per l'invio di dati al server: si potrebbe provare lo stesso nel proprio script.

IME, la maggior parte delle situazioni in cui si tratta di un problema può essere meglio affrontato da ....

register_shutdown_function('do_slow_stuff'); 
....generate html content.... 
exit; // closes stdin/stdout, but shutdown fn will still be called 

function do_slow_stuff() 
{ 
    .... 
} 
4

Immettere il seguente comando come amministratore in PowerShell:

C:\Windows\System32\inetsrv> .\appcmd.exe set config /section:handlers "/[name='PHP_via_FastCGI'].ResponseBufferLimit:0" 

Output previsto:

Modifiche apportate alla sezione "Sistema".webserver/gestori" per "MACHINE/WEBROOT/APPHOST" alla configurazione comm esso percorso "MACCHINA/WEBROOT/APPHOST"

per più di fondo, hanno un'occhiata a: http://www.coastrd.com/cgioniis7

In sostanza, abbiamo bisogno . raccontare FastCGI per trasformare la sua ResponseBufferLimit Questo non può essere fatto attraverso la console di gestione di IIS (controllato solo 7.5)

23

C'è un altro modo per impostare il limite di risposta utilizzando la Gestione IIS:

  1. Nella pagina principale del server, in "Gestione", selezionare "Editor di configurazione";
  2. in "Sezione", immettere "system.webServer/handlers";
  3. accanto a "(Collezione)" fare clic su "..." O contrassegnare l'elemento "(Collezione)" e, sotto "Azioni" e "Elemento (Raccolta)", fare clic su "Modifica elementi";
  4. scorrere verso il basso fino a trovare la versione di PHP in "Nome";
  5. nella parte inferiore, le Proprietà sono mostrate e possono essere modificate manualmente, incluso responseBufferLimit, che dovrebbe essere impostato su 0 affinché flush() funzioni.

Il grande Pro è che è possibile modificare le proprietà per tutto, non solo PHP in più si può lavorare con diverse versioni (o anche installazioni della stessa versione) di PHP.

HTH

+2

+1 eccellente! Questa è la prima volta che vedo una soluzione per impostare responsebufferlimit tramite il gestore IIS. – Rich

+0

Questo è il miglior soution. Grazie –

2

Sono un po 'in ritardo per la festa, ma ho pensato di aggiungere come farlo con web.config.

<?xml version="1.0" encoding="UTF-8"?> 
<configuration> 
     <!--- other stuff here ---> 
     <handlers> 
      <remove name="ISAPI-dll" /> 
      <add name="ISAPI-dll" path="*.dll" verb="*" type="" modules="IsapiModule" scriptProcessor="" resourceType="File" requireAccess="Execute" allowPathInfo="true" preCondition="" responseBufferLimit="0" /> 
     </handlers> 
    </system.webServer> 
</configuration> 
0

Ecco un altro modo per farlo con web.config (il metodo @ Jules non ha funzionato con IIS 8.0). Ovviamente, vorrai sostituire le versioni e i percorsi di PHP con quelli effettivamente presenti sulla tua macchina.

Ciò consente l'utilizzo di eventi inviati dal server!

<configuration> 
    <system.webServer> 
     <handlers> 
      <remove name="PHP53_via_FastCGI" /> 
      <remove name="PHP54_via_FastCGI" /> 
      <remove name="PHP55_via_FastCGI" /> 
      <add name="PHP53_via_FastCGI" path="*.php" verb="GET,HEAD,POST" type="" modules="FastCgiModule" scriptProcessor="C:\Program Files (x86)\PHP\v5.3\php-cgi.exe" resourceType="Either" requireAccess="Script" allowPathInfo="true" preCondition="" responseBufferLimit="0" /> 
      <add name="PHP54_via_FastCGI" path="*.php" verb="GET,HEAD,POST" type="" modules="FastCgiModule" scriptProcessor="C:\Program Files (x86)\PHP\v5.4\php-cgi.exe" resourceType="Either" requireAccess="Script" allowPathInfo="true" preCondition="" responseBufferLimit="0" /> 
      <add name="PHP55_via_FastCGI" path="*.php" verb="GET,HEAD,POST" type="" modules="FastCgiModule" scriptProcessor="C:\Program Files (x86)\PHP\v5.5\php-cgi.exe" resourceType="Either" requireAccess="Script" allowPathInfo="true" preCondition="" responseBufferLimit="0" /> 
     </handlers> 
    </system.webServer> 
</configuration>