Programing

각`echo` 호출 후 출력을 플러시하는 방법은 무엇입니까?

crosscheck 2021. 1. 9. 10:41
반응형

각`echo` 호출 후 출력을 플러시하는 방법은 무엇입니까?


클라이언트에 로그 만 생성하는 PHP 스크립트가 있습니다.
내가 무언가를 에코 할 때 즉시 클라이언트에게 전송되기를 원합니다.
(스크립트가 처리되는 동안 페이지가 비어 있기 때문에)
이미 ob_start()을 사용해 ob_flush()보았지만 작동하지 않았습니다.

최상의 솔루션은 무엇입니까?

추신 : echo통화 가 끝날 때 플러시를 두는 것이 조금 더럽습니다 ...

편집 : 답변이 작동하지 않았거나 PHP 또는 Apache 오류가 있습니까?


편집하다:

나는 매뉴얼 페이지에서 칭찬을 읽고 작동하지 않는다는 버그 를 발견 했으며 다음은 이에 대한 해결 방법입니다.ob_implicit_flush

ob_end_flush();

# CODE THAT NEEDS IMMEDIATE FLUSHING

ob_start();

일어날 수있는 일은 서버가 보낼 가치가있는 것으로 간주되는 패킷을 보낼 수있는 충분한 문자를 서버가 구축 할 때까지 클라이언트가 서버로부터 패킷을 수신하지 않는다는 것입니다.


이전 답변 :

ob_implicit_flush잠시 동안 버퍼링을 끄도록 출력 버퍼링에 지시하는 것을 사용할 수 있습니다 .

ob_implicit_flush(true);

# CODE THAT NEEDS IMMEDIATE FLUSHING

ob_implicit_flush(false);

동일한 문제가 발생했으며 매뉴얼에 게시 된 예제 중 하나가 작동했습니다. 여기에서 이미 언급 한 포스터 중 하나로 문자 집합을 지정해야합니다. http://www.php.net/manual/en/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 />';

그래서 여기에 제가 알아 낸 것이 있습니다.

Flush는 Apache의 mod_gzip 또는 Nginx의 gzip에서 작동하지 않습니다. 논리적으로 콘텐츠를 gzip으로 압축하고이를 수행하려면 콘텐츠를 gzip으로 버퍼링해야하기 때문입니다. 모든 종류의 웹 서버 gzipping이 이에 ​​영향을 미칩니다. 즉, 서버 측에서는 gzip을 비활성화하고 fastcgi 버퍼 크기를 줄여야합니다. 그래서:

  • php.ini에서 :

    output_buffering = Off
    
    zlib.output_compression = Off
    
  • nginx.conf에서 :

    gzip  off;
    
    proxy_buffering  off;
    

특히 php.ini에 액세스 할 수없는 경우 다음 줄을 준비하십시오.

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

@ini_set('implicit_flush',1);

@ob_end_clean();

set_time_limit(0);

마지막으로, 가지고 있다면 아래 코드에 주석을 달아주세요 :

ob_start('ob_gzhandler');

ob_flush();

PHP 테스트 코드 :

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

플러싱이 작동하지 않는 것처럼 보이는 것은 자동 문자 집합 감지의 부작용입니다.

브라우저는 그것을 표시 할 문자 세트를 알 때까지 아무것도 표시하지 않으며 문자 세트를 지정하지 않으면 추측을 시도해야합니다. 문제는 충분한 데이터 없이는 좋은 추측을 할 수 없다는 것입니다. 이것이 브라우저가 아무것도 표시하기 전에 채워야하는 1024 바이트 (또는 유사한) 버퍼를 가지고있는 이유입니다.

따라서 해결책은 브라우저가 문자 집합을 추측 할 필요가 없도록하는 것입니다.

문자를 보내는 경우 '; charset = utf-8 '을 콘텐츠 유형에 추가하고 HTML 인 경우 적절한 메타 태그에 문자 집합을 추가합니다.


2018 년 출시 예정인 경우 :

유일한 솔루션이 저에게 효과적이었습니다.

<?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();
?>

버퍼를 "채운"것처럼 보이기 때문에 "4096"부분을 유지하는 것이 매우 중요합니다.


당신이 원하는 것은 플러시 방법입니다. 예:

echo "log to client";
 flush();

다음과 같이 에코 할 함수를 만드는 것은 어떨까요?

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

사용할 올바른 기능은 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>

IE에는 "문제"가있어서 최소 256 바이트 일 때만 플러시 된 콘텐츠를 출력하므로 페이지의 첫 번째 부분은 최소 256 바이트 여야합니다.


나는 비슷한 일을했다. 사용

// ini_set("output_buffering", 0);  // off 
ini_set("zlib.output_compression", 0);  // off
ini_set("implicit_flush", 1);  // on   

내 경우에는 출력이 자주 플러시되었습니다.

하지만 특정 지점 (내가 실행하는 루프에서)에서 바로 출력을 플러시해야했기 때문에

ob_flush();
flush();

함께 일했습니다.

내가 해제 할 수 없습니다 "output_buffering을" 는 ini_set으로 (...), php.ini 파일에서 직접 설정했다,은 phpinfo ()는 그 정상 꺼져 "값이 없음"등의 설정을 보여줍니다? .


자주 언급되지 않는 한 가지는 다양한 호스팅 환경의 세부 사항으로 인해 계속 켜져있는 gzip 압축입니다.

Here is a modern approach, working with PHP-FPM as Fast CGI, which does not need .htaccess rewrite rule or environment variable :

In php.ini or .user.ini :

output_buffering = 0
zlib.output_compression = 0
implicit_flush = true
output_handler = 

In PHP script :

header('Content-Encoding: none'); // Disable gzip compression
ob_end_flush(); // Stop buffer
ob_implicit_flush(1); // Implicit flush at each output command

See this comment on official PHP doc for ob_end_flush() need.


Anti-virus software may also be interfering with output flushing. In my case, Kaspersky Anti-Virus 2013 was holding data chunks before sending it to the browser, even though I was using an accepted solution.


This works fine for me (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";

Try this:

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

Just notice that this way you're actually disabling the output buffer for your current script. I guess you can reenable it with ob_start() (i'm not sure).

Important thing is that by disabling your output buffer like above, you will not be able to redirect your php script anymore using the header() function, because php can sent only once per script execution http headers. You can however redirect using javascript. Just let your php script echo following lines when it comes to that:

        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;

Note if you are on certain shared hosting sites like Dreamhost you can't disable PHP output buffering at all without going through different routes:

Changing the output buffer cache If you are using PHP FastCGI, the PHP functions flush(), ob_flush(), and ob_implicit_flush() will not function as expected. By default, output is buffered at a higher level than PHP (specifically, by the Apache module mod_deflate which is similar in form/function to mod_gzip).

If you need unbuffered output, you must either use CGI (instead of FastCGI) or contact support to request that mod_deflate is disabled for your site.

https://help.dreamhost.com/hc/en-us/articles/214202188-PHP-overview


I'm late to the discussion but I read that many people are saying appending flush(); at the end of each code looks dirty, and they are right.

Best solution is to disable deflate, gzip and all buffering from Apache, intermediate handlers and PHP. Then in your php.ini you should have:

            output_buffering = Off
            zlib.output_compression = Off
            implicit_flush = Off

Temporary solution is to have this in your php.ini IF you can solve your problem with flush(); but you think it is dirty and ugly to put it everywhere.

implicit_flush = On

If you only put it above in your php.ini, you don't need to put flush(); in your code anymore.


This is my code: (work for 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();
}

Sometimes, the problem come from Apache settings. Apache can be set to gzip the output. In the file .htaccess you can add for instance :

SetEnv no-gzip 1

ReferenceURL : https://stackoverflow.com/questions/3133209/how-to-flush-output-after-each-echo-call

반응형