PHP实时输出需先关闭输出缓冲、禁用zlib压缩,并设置Content-Type、X-Accel-Buffering、Cache-Control三个关键Header,每次输出后调用flush()和ob_flush(),补充空格与换行符以触发浏览器渲染。

PHP实时输出前必须关闭输出缓冲
PHP默认开启输出缓冲(output_buffering),不关掉它,echo、print 再多也看不到“实时”效果。光设 header 没用,得先让内容真正发出去。
实操建议:
- 开头立即调用
ob_end_flush()或ob_get_level() > 0 && ob_end_clean()清空并关闭已有缓冲 - 确保
php.ini中output_buffering = Off,或在脚本开头加ini_set('output_buffering', 'Off')(部分环境生效) - 禁用 zlib 压缩:
ini_set('zlib.output_compression', 'Off'),否则压缩层会拦截流式输出
必须设置的三个关键Header
浏览器要持续接收并渲染内容,不是所有 header 都管用。以下三项缺一不可,顺序无关但必须存在:
-
header('Content-Type: text/plain; charset=utf-8')—— 明确类型,避免浏览器因猜测 MIME 而延迟渲染 -
header('X-Accel-Buffering: no')—— Nginx + FastCGI 场景下绕过其内部缓冲(否则白设) -
header('Cache-Control: no-cache')—— 阻止代理或浏览器缓存整块响应,影响流式更新
注意:Expires 或 Pragma 单独设不够,Cache-Control 是现代标准且优先级更高。
立即学习“PHP免费学习笔记(深入)”;
每次输出后必须 flush,且要防浏览器“攒包”
仅 echo + flush() 不够。现代浏览器(尤其 Chrome)会对小块文本做渲染优化,可能等满 1KB 或遇到换行才刷屏。
实操建议:
- 每次输出后调用
flush()和ob_flush()(如果之前没彻底关缓冲) - 在内容末尾补足够空白(如
str_repeat(" ", 4096))填满 TCP 包,触发浏览器尽早渲染 - 输出换行符
\n很重要,HTML 模式下可用,但纯文本流更依赖\n作为刷新提示
CLI 与 Web SAPI 行为差异极大
同一段 flush 代码,在 php script.php(CLI)里总能实时打印,但在 Apache/Nginx 下大概率失效——根本原因是 SAPI 层附加了缓冲逻辑。
排查要点:
- 用
php_sapi_name()确认当前是fpm-fcgi、apache2handler还是cli - FPM 场景下,还需检查
fastcgi_buffering off(Nginx)或proxy_buffering off(Apache mod_proxy) - 某些 CDN(如 Cloudflare)会强制缓冲,实时输出需关闭其“优化”功能或改用 WebSocket 替代
真实项目里,最常被忽略的是反向代理层的二次缓冲——header 设再全,卡在 Nginx 那一层就全白搭。











