Ich habe ein PHP-Skript, das nur Protokolle an den Client erstellt.
Wenn ich etwas wiederhole, möchte ich, dass es on-the-fly an den Client übertragen wird.
(Während das Skript verarbeitet wird, ist die Seite leer.)
Ich hatte bereits mit ob_start()
und ob_flush()
herumgespielt, aber sie funktionierten nicht.
Was ist die beste Lösung?
PS: Es ist ein bisschen schmutzig, am Ende des echo
-Aufrufs einen Flush zu setzen ...
EDIT: Weder die Antworten funktionierten, PHP noch Apache-Fehler?
Bearbeiten:
Ich las die Kommentare auf der Handbuchseite und stieß auf einen Fehler der besagt, dass ob_implicit_flush
funktioniert nicht und Folgendes ist eine Problemumgehung dafür:
ob_end_flush();
# CODE THAT NEEDS IMMEDIATE FLUSHING
ob_start();
Es kann sogar vorkommen, dass der Client das Paket nicht vom Server empfängt, bis der Server genügend Zeichen aufgebaut hat, um ein Paket zu senden, von dem es empfehlenswert ist, dass es gesendet wird.
Alte Antwort:
Sie könnten ob_implicit_flush
verwenden, um die Pufferung für eine Weile zu deaktivieren:
ob_implicit_flush(true);
# CODE THAT NEEDS IMMEDIATE FLUSHING
ob_implicit_flush(false);
Ich habe das gleiche Problem bekommen und eines der im Handbuch veröffentlichten Beispiele hat funktioniert. Ein Zeichensatz muss als eines der bereits erwähnten Poster angegeben werden. http://www.php.net/manual/de/function.ob-flush.php#109314
header( 'Content-type: text/html; charset=utf-8' );
echo 'Begin ...<br />';
for( $i = 0 ; $i < 10 ; $i++ )
{
echo $i . '<br />';
flush();
ob_flush();
sleep(1);
}
echo 'End ...<br />';
Also hier ist was ich herausgefunden habe.
Flush funktioniert nicht unter Apache's mod_gzip oder Nginxs gzip, da logischerweise der Inhalt gzipiert wird und dazu der Inhalt gepuffert werden muss, um ihn zu gzipieren. Jede Art von Webserver-Import würde dies beeinflussen. Kurz gesagt, auf der Serverseite müssen wir gzip deaktivieren und die fastcgi-Puffergröße verringern. So:
In php.ini:
output_buffering = Off
zlib.output_compression = Off
In nginx.conf:
gzip off;
proxy_buffering off;
Halten Sie auch diese Zeilen bereit, insbesondere wenn Sie keinen Zugriff auf die php.ini haben:
@ini_set('zlib.output_compression',0);
@ini_set('implicit_flush',1);
@ob_end_clean();
set_time_limit(0);
Wenn Sie es haben, kommentieren Sie den Code wie folgt:
ob_start('ob_gzhandler');
ob_flush();
PHP Testcode:
ob_implicit_flush(1);
for ($i=0; $i<10; $i++) {
echo $i;
// this is to make the buffer achieve the minimum size in order to flush data
echo str_repeat(' ',1024*64);
sleep(1);
}
Das Flushing, das scheinbar nicht funktioniert, ist ein Nebeneffekt der automatischen Zeichensatzerkennung.
Der Browser zeigt nichts an, bis er den Zeichensatz kennt, in dem er angezeigt werden soll. Wenn Sie den Zeichensatz nicht angeben, muss er versucht werden, ihn zu erraten. Das Problem ist, dass es ohne ausreichende Daten keine gute Vermutung geben kann. Deswegen scheinen die Browser diesen 1024 Byte (oder ähnlichen) Puffer zu haben, den sie füllen müssen, bevor sie etwas anzeigen.
Die Lösung ist daher sicherzustellen, dass der Browser den Zeichensatz nicht erraten muss.
Wenn Sie Text senden, fügen Sie ein '; charset = utf-8 'zu seinem Inhaltstyp und wenn es HTML ist, fügen Sie den Zeichensatz dem entsprechenden Metatag hinzu.
was Sie wollen, ist die flush method . Beispiel:
echo "log to client";
flush();
Für diejenigen, die 2018 kommen:
Die EINZIGE Lösung funktionierte für mich:
<?php
if (ob_get_level() == 0) ob_start();
for ($i = 0; $i<10; $i++){
echo "<br> Line to show.";
echo str_pad('',4096)."\n";
ob_flush();
flush();
sleep(2);
}
echo "Done.";
ob_end_flush();
?>
und es ist sehr wichtig, den Teil "4096" beizubehalten, da es den Anschein hat, dass er den Puffer "füllt" ...
Warum nicht eine Funktion als Echo erstellen?
function fecho($string) {
echo $string;
ob_flush();
}
Ich hatte eine ähnliche Sache zu tun. Verwenden
// ini_set("output_buffering", 0); // off
ini_set("zlib.output_compression", 0); // off
ini_set("implicit_flush", 1); // on
machte die Ausgabespülung in meinem Fall häufig.
Aber ich musste die Ausgabe direkt an einem bestimmten Punkt (in einer Schleife, die ich ausführte) spülen, also beide verwenden
ob_flush();
flush();
zusammen gearbeitet für mich.
Ich konnte es nicht. Deaktivieren Sie "output_buffering" mit ini_set (...), musste es direkt drehen In php.ini zeigt phpinfo () seine Einstellung als "kein Wert" im ausgeschalteten Zustand ist das normal? .
Die korrekte Funktion ist flush()
.
<html>
<body>
<p>
Hello! I am waiting for the next message...<br />
<?php flush(); sleep(5); ?>
I am the next message!<br />
<?php flush(); sleep(5); ?>
And I am the last message. Good bye.
</p>
</body>
</html>
Bitte beachten Sie, dass es ein Problem mit IE gibt, das den gelöschten Inhalt nur dann ausgibt, wenn er mindestens 256 Byte groß ist. Daher muss Ihr erster Teil der Seite mindestens 256 Byte groß sein.
Das funktioniert gut für mich (Apache 2.4/PHP 7.0):
@ob_end_clean();
echo "lorem ipsum...";
flush();
sleep(5);
echo "<br>dolor...";
flush();
sleep(5);
echo "<br>sit amet";
Antiviren-Software kann auch die Ausgabespülung stören. In meinem Fall hielt Kaspersky Anti-Virus 2013 Datenblöcke vor dem Senden an den Browser, obwohl ich eine akzeptierte Lösung verwendete.
Dies ist mein Code: (Arbeit für PHP7)
private function closeConnection()
{
@Apache_setenv('no-gzip', 1);
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);
ignore_user_abort(true);
set_time_limit(0);
ob_start();
// do initial processing here
echo json_encode(['ans' => true]);
header('Connection: close');
header('Content-Length: ' . ob_get_length());
ob_end_flush();
ob_flush();
flush();
}
Ich komme zu spät zur Diskussion, aber ich habe gelesen, dass viele Leute Appending Flush () sagen. am ende sieht jeder code dreckig aus und sie haben recht.
Beste Lösung ist das Deaktivieren von deflate, gzip und allen Puffern von Apache, Intermediate Handlern und PHP. Dann solltest du in deiner php.ini haben:
output_buffering = Off
zlib.output_compression = Off
implicit_flush = Off
Temporäre Lösung soll dies in Ihrer php.ini haben WENN Sie können Ihr Problem mit flush () lösen; Aber du denkst, es ist schmutzig und hässlich, es überall hin zu stellen.
implicit_flush = On
Wenn Sie es nur in Ihre php.ini einfügen, brauchen Sie flush () nicht zu setzen. in Ihrem Code mehr.
Versuche dies:
while (@ob_end_flush());
ob_implicit_flush(true);
echo "first line visible to the browser";
echo "<br />";
sleep(5);
echo "second line visible to the browser after 5 secs";
Beachten Sie, dass Sie auf diese Weise tatsächlich den Ausgabepuffer für Ihr aktuelles Skript deaktivieren. Ich denke, Sie können es mit ob_start () wieder aktivieren (ich bin mir nicht sicher).
Wichtig ist, dass Sie durch Deaktivieren des Ausgabepuffers (siehe oben) Ihr PHP-Skript nicht mehr mit der Funktion header()
umleiten können, da PHP nur einmal pro http-Header der Skriptausführung gesendet werden kann. Sie können jedoch mithilfe von Javascript umleiten. Lassen Sie Ihr PHP-Skript die folgenden Zeilen wiedergeben, wenn es dazu kommt:
echo '<script type="text/javascript">';
echo 'window.location.href="'.$url.'";';
echo '</script>';
echo '<noscript>';
echo '<meta http-equiv="refresh" content="0;url='.$url.'" />';
echo '</noscript>';
exit;
Eine Sache, die nicht oft erwähnt wird, ist die gzip-Komprimierung, die aufgrund von Details in verschiedenen Hosting-Umgebungen eingeschaltet bleibt.
Hier ist ein moderner Ansatz, der mit PHP-FPM als Fast CGI arbeitet und keine .htaccess-Umschreiberegel oder Umgebungsvariable benötigt:
In php.ini oder .user.ini:
output_buffering = 0
zlib.output_compression = 0
implicit_flush = true
output_handler =
In PHP Skript:
header('Content-Encoding: none'); // Disable gzip compression
ob_end_flush(); // Stop buffer
ob_implicit_flush(1); // Implicit flush at each output command
Siehe diesen Kommentar im offiziellen PHP doc für ob_end_flush ().
Wenn Sie sich auf bestimmten Shared-Hosting-Sites wie Dreamhost befinden, können Sie die Ausgabepufferung von PHP überhaupt nicht deaktivieren, ohne verschiedene Wege zu gehen:
Ausgabepuffercache ändern Wenn Sie PHP FastCGI verwenden, wird der PHP Die Funktionen flush (), ob_flush () und ob_implicit_flush () werden nicht Funktion wie erwartet. Standardmäßig wird die Ausgabe auf einer höheren Ebene gepuffert als PHP (insbesondere durch das Apache-Modul mod_deflate, das in form/Funktion ähnlich wie mod_gzip ist).
Wenn Sie eine ungepufferte Ausgabe benötigen, müssen Sie entweder CGI (anstelle von FastCGI) verwenden oder den Support an anfragen, dass mod_deflate .__ deaktiviert ist. für deine Seite.
https://help.dreamhost.com/hc/de-de/articles/214202188-PHP-overview