2013-02-22 10 views
6

Ich habe ein PHP-Skript, das eine große Anzahl von Datensätzen sendet, und ich möchte jeden Datensatz leeren, sobald es verfügbar ist: Der Client ist in der Lage, jeden Datensatz zu verarbeiten, wie es ankommt muss nicht auf die gesamte Antwort warten. Ich weiß, dass es für die gesamte Übertragung ein wenig länger dauert, da es in mehreren Paketen gesendet werden muss, aber es dem Client dennoch ermöglicht, schneller zu arbeiten.Verhindern Ausgabe Pufferung mit PHP und Apache

Ich habe versucht, die verschiedenen flush() und ob_flush() Funktionen, aber nichts scheint zu helfen, die Daten tatsächlich über die Leitung gesendet werden, bevor die Seite fertig ist. Ich habe bestätigt, dass es nicht der Webbrowser ist, weil ich es mit Telnet getestet habe.

Antwort

4

Die einzige Lösung, die für mich funktionierte, war, die output_buffering Direktive in php.ini auf "Aus" zu setzen. Ich wollte das nicht für den gesamten Server tun, nur diese eine spezifische Ressource. Normalerweise könnten Sie ini_set aus dem PHP-Skript verwenden, aber aus welchem ​​Grund auch immer, php erlaubt output_buffering nicht auf diese Weise zu setzen (siehe the php manual).

Nun, es stellt sich heraus, dass wenn Sie Apache verwenden, können Sie einige PHP-Ini-Anweisungen (einschließlich output_buffering) von Ihrer Server-Konfiguration, einschließlich einer .htaccess-Datei. So habe ich die folgend in einer .htaccess-Datei den output_buffering nur für diese eine Datei zu deaktivieren:

<Files "q.php"> 
    php_value output_buffering Off 
</Files> 

Und dann in meiner statischen Server-Konfiguration, ich brauche nur AllowOverride Options=php_value (oder einen größerer Hammer, wie AllowOverride All), um Damit dies in einer .htaccess-Datei erlaubt ist.

+1

Nicht sicher, ob das immer falsch war oder etwas in PHP5.6 geändert hat, aber ich musste 'php_flag output_buffering Off' verwenden, um das' Off' zu erhalten. – RiggsFolly

+0

Ich habe "output_buffering" von php.ini von 4096 auf Aus gesetzt und den gesamten Server neu gestartet, verifiziert mit phpinfo(); aber ich habe immer noch das selbe Problem, der Server wartet auf das Laden der Seite, bevor Daten an den Browser gesendet werden. Gibt es eine andere Einstellung in Apache2 oder Ubuntu 16.04? Ich benutze PHP7. – Tarik

3

Sie erwähnen nicht, welchen Webserver Sie verwenden, aber ich gehe hier ein bisschen aus und denke Apache2. Ich habe fast das identische Ding getroffen, das du beschreibst. Ich habe versucht, mein CGI-Skript dazu zu bringen, Informationen zurück zu geben, so wie es fertig war, anstatt das Ganze zu puffern. Arbeitete jiffy in curl, etc., aber gepuffert in einem Browser (so ziemlich jeder Browser), was zumindest ärgerlich war. Ich ging die genauen Schritte durch, die Sie beschreiben. Die Auflösung in meinem Fall sites-enabled/terrifico.com Konfigurationsdatei in Apache2 (die fragliche Zeile beginnt mit

SetEnvIfNoCase

(Sie können ignorieren das Zeug oberhalb und unterhalb dieser Linie zu ändern war, bin ich nur zeigen, es als Referenz, wo ich ihm gegeben.)

<VirtualHost *:80> 
ServerAdmin [email protected] 
ServerName test.terrifico.com 
ServerAlias test.terrifico.com 

SetEnvIfNoCase Request_URI \.cgi$ no-gzip dont-vary 

DocumentRoot /var/www/test.terrifico.com 

von im Netzwerkverkehr und starren hin und her, es dämmerte schließlich auf mir, dass der Browser war Werbung, dass es eine Deflation für alles akzeptiert (das war Text). Das war zum Beispiel der Unterschied zwischen Browser und Curl. Die ausgeprägte Bit war

Accept-Encoding: gzip, deflate, sdch

Es war ein bisschen über chunking, aber das hat nicht dieses besondere Problem auswirken. Also bat der Browser um mod_deflate, um zu kicken, was meine sorgfältig ausspuckenden Bytes besiegte, als ich sie in meinem CGI-Skript bekam. Sie könnten es im Browser ändern, aber es schien sinnvoller, es einmal auf dem Server für die Arbeiten zu ändern.

Vielleicht hilft das.

2

Um nur ohne Ausgabepufferung zur Laufzeit in PHP Ändern php.ini oder mit einer .htaccess Datei verwenden ob_end_flush() oder ob_end_clean() am Anfang des Skripts zu deaktivieren. Zum Beispiel:

Dies ausgeben sollte ohne Pufferung:

<?php 
ob_end_clean(); 

for ($i = 0; $i < 5; $i++) 
{ 
    echo "$i\n"; 
    flush(); 
    usleep(0.5e6); 
} 

Diese Ausgänge mit Pufferung (alle auf einmal), wenn output_buffering eingeschaltet ist, unabhängig von dem flush() Call:

<?php 

for ($i = 0; $i < 5; $i++) 
{ 
    echo "$i\n"; 
    flush(); 
    usleep(0.5e6); 
} 

Trotz ihrer Name, ob_implicit_flush Aufrufe flush(), nicht ob_flush(), implizit nach jedem Ausgang. Dies kann in diesem Fall nützlich sein, wenn der Ausgangspuffer am Anfang geschlossen wird:

Dies behebt die PHP-Seite. Es kann etwas anderes mit mod_deflate oder ähnlichem passieren (siehe die Antwort von Ted Collins), und ich habe beobachtet, dass Firefox mindestens 1024 Bytes benötigt, bevor es überhaupt beginnt, etwas auszugeben.

+0

Dieser Code macht 3x gleich -.- –

Verwandte Themen