web-dev-qa-db-de.com

Wie bereinige ich die Ausgabe nach jedem "Echo" -Aufruf?

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? 

47
CuSS

Bearbeiten:

Ich las die Kommentare auf der Handbuchseite und stieß auf einen Fehler der besagt, dass ob_implicit_flushfunktioniert 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);
32
amphetamachine

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 />';
56
Teno

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);
}
29
Roger

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.

10
nobody

was Sie wollen, ist die flush method . Beispiel:

echo "log to client";
 flush();
7
GSto

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" ...

7
Ari Waisberg

Warum nicht eine Funktion als Echo erstellen?

function fecho($string) {
 echo $string;
 ob_flush();
}
5
cam8001

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? .

3
freedayum

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.

2
Dennis G

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";
1
Radacina

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. 

1
marcovtwout

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();
}
0
Dmitry Matrosov

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.

0
Tarik

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;
0
Grigoreas P.

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 ().

0
ZalemCitizen

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

0
Matthew Lock