PHP flush не работает
<?php
for($i=0;$i<20;$i++)
{
echo 'printing...<br />';
ob_flush();
flush();
usleep(300000);
}
?>
Url, содержащий код:http://domainsoutlook.com/sandbox/delayed.php
У меня есть выделенный сервер, поэтому я могу внести изменения. Я запускаю apache и nginx в качестве прокси-сервера.
12 ответов
вы используете ob_flush
без ob_start
, поэтому нет ничего, чтобы смыть его.
Это также зависит от веб-сервера и прокси-сервера и его настроек.
вы должны отключить буферизацию для Nginx (добавить "proxy_buffering off;" в конфигурационный файл и перезапустить Nginx)
кроме того, проверьте, если ваш PHP.ini содержит "output_buffering = Off" и " zlib.output_compression = Off".
вот что я узнал:
Flush не будет работать под mod_gzip Apache или gzip Nginx, потому что, логически, это gzipping содержимого, и для этого он должен буферизировать содержимое для gzip. Любой вид веб-сервера gzipping повлияет на это. Короче говоря, на стороне сервера нам нужно отключить gzip и уменьшить размер буфера fastcgi. Итак:
-
в php.ini:
. output_buffering = выкл
. с zlib.output_compression = Выкл
-
в nginx.conf:
. gzip off;
. proxy_buffering off;
также есть эти линии под рукой, особенно если у вас нет доступа к РНР.ini:
@безопасность('zlib в.output_compression',0);
@безопасность('implicit_flush',1);
@ob_end_clean ();
set_time_limit(0);
последний, если он у вас есть, coment код ниже:
ob_start ('ob_gzhandler');
помощью ob_flush();
тест PHP код:
ob_implicit_flush(1);
for($i=0; $i<10; $i++){
echo $i;
//this is for the buffer achieve the minimum size in order to flush data
echo str_repeat(' ',1024*64);
sleep(1);
}
основной файл php;
<?php
header('Content-Type: text/HTML; charset=utf-8');
header( 'Content-Encoding: none; ' );//disable apache compressed
session_start();
ob_end_flush();
ob_start();
set_time_limit(0);
error_reporting(0);
..... bla bla
for(each)........
{
bla bla..
echo "<br>>>>".$i."<<<br>";
ob_flush();
flush(); //ie working must
}
?>
это работает..
другой возможной причиной является mod_security. Похоже, у него есть собственные буферы. Поэтому, если вы используете его, вам нужно будет установить:
SecResponseBodyAccess Off
вид грязного обходного пути, но до сих пор это единственный способ заставить его работать.
вы должны заполнить буфер, чтобы его можно было сбросить в браузер. Используйте это после echo
echo str_pad('',4096)."\n";
полный код:
<?php
if (ob_get_level() == 0) ob_start();
for( $i=0 ; $i<20 ; $i++) {
echo 'printing...<br />';
echo str_pad('',4096)."\n";
ob_flush();
flush();
usleep(300000);
}
ob_end_flush();
?>
просто хотел добавить к ответу Роджера.
Если вы используете FastCGI пакета php5-ФПМ модуль внутри apache2 не вы также должны убедиться, что вы добавляете
-flush
аргумент в вашей конфигурации Apache2, т. е.
<IfModule mod_fastcgi.c>
...
FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -flush -socket /tmp/php5-fpm.sock -idle-timeout 480 -pass-header Authorization
</IfModule>
когда я читаю, кажется, действительно трудно решить pb, и единственный (грязный) способ, который я нашел, - это написать что-то бесполезное для вывода, чтобы заполнить буферы≠. - без ssl - без output_buffering, приток необходим, буферы nginx можно понизить до размера заголовка php - с output_buffering, ob_flush нужно добавить, чтобы иметь то же поведение, что и выше - с ssl, есть еще один буфер для ssl и NGX_SSL_BUFSIZE фиксируется в компиляции nginx
вот мой тест.PHP-файл (позвонить ?размер.=.. чтобы изменить пробел записи в цикле)
<!DOCTYPE html>
<html>
<head></head>
<body>
<?php
$vars = array('output_buffering', 'zlib.output_compression');
print('<p>');
foreach ($vars as $var) {
print("$var : ");
var_dump(ini_get($var));
print('<br />');
}
print("ob_get_level() : " .ob_get_level());
print('</p>');
if (ob_get_level()) {
$bytes = ob_get_length();
ob_flush();
}
$nb_iterations = !empty($_GET['nb']) ? max(2, (int) $_GET['nb']) : 5;
$size = !empty($_GET['size']) ? $_GET['size'] : 0;
for ($i = 1; $i < $nb_iterations; $i++) {
sleep(1);
print(str_repeat(' ', 1024 * $size ));
print("<p>wait $i s</p>");
if (ob_get_level()) {
$bytes += ob_get_length();
print($bytes + strlen($bytes));
ob_flush(); // this is working, results aren't depending on output_buffering value
}
flush(); // this is needed
}
?>
</body>
</html>
и Нижний conf, который я могу установить, -
location ~ ^/test.php$ {
gzip off;
fastcgi_pass unix:/var/run/php5-fpm/ssl.socket;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param SCRIPT_FILENAME $request_filename;
# if too low => upstream sent too big header while reading response header from upstream
fastcgi_buffer_size 128;
fastcgi_buffers 2 128;
fastcgi_busy_buffers_size 128;
}
в php.ini:
output_buffering = выкл. с zlib.output_compression = Off
в nginx.conf:
fastcgi_keep_conn on; #
proxy_buffering от; gzip off;
Я заметил, что браузеры по-разному реагируют. Chrome, например, держится за вход навсегда и, похоже, не заботится о его отображении раньше. Неудивительно, что Firefox отобразит ввод раньше, если применяются вышеуказанные советы (предоставленные другими stackoverflowers), поэтому попробуйте с Firefox.
я смог смыть только таким образом-добавление session_write_close ();
if (ob_get_level() == 0)
{
if(!ob_start("ob_gzhandler"))ob_start();
}
echo ('bla bla bla');
$ans=ob_get_contents();
ob_end_clean();
header('Connection: close');
header('Content-Length: '.strlen($ans));
header('Status: 200');
echo $ans;
session_write_close();
ob_flush();
flush();
Проверьте api сервера с помощью
echo phpinfo();
если вы нашли свой сервер API
Server API : CGI/FastCGI
в CentOS затем добавьте эту строку в " /etc/httpd / conf.d / fcgid.conf"
OutputBufferSize 0
чтобы проверить, перезагрузите сервер Apache и попробуйте ниже код
ob_start();
for($i = 0; $i < 10; $i ++) {
echo $i;
echo '<br />';
flush();
ob_flush();
sleep(1);
}
if(!ob_get_level()) ob_start();
echo json_encode(array('valid'=>true,'msg'=>'Flush occured.'));
$size = ob_get_length();
header("Content-Type: application/json");
// Set the content length of the response.
header("Content-Length: {$size}");
//Close the connection if you want to.
header("Connection: close");
// Flush all output.
ob_end_flush();
ob_flush();
flush();
// Close current session (if it exists).
if(session_id()) session_write_close();