PHP实时输出卡在“加载中”的根本原因是服务端未发送完整响应头或输出缓冲未正确刷新;需关闭PHP输出缓冲、手动刷新并处理Web服务器缓冲层,同时注意反向代理与浏览器兼容性。

PHP实时输出时浏览器一直显示“加载中”
根本原因是服务端没有发送完整的HTTP响应头,或者输出缓冲未正确刷新,导致浏览器认为响应尚未结束。PHP默认启用输出缓冲(output_buffering),所有echo或print内容会先存入缓冲区,直到脚本结束或缓冲区满才真正发出——这会让前端卡在“加载中”状态,哪怕你每秒都在echo。
解决的关键是三件事:关闭默认缓冲、手动刷新输出、确保响应头已发送。常见错误包括只调用flush()却没关ob_end_flush(),或忽略Web服务器(如Nginx)的额外缓冲层。
- 在脚本开头立即调用
ob_end_clean()或ob_get_clean(),清除并关闭所有已启动的输出缓冲 - 调用
ini_set('output_buffering', 'off')和ini_set('zlib.output_compression', 'off'),禁用PHP级缓冲与压缩 - 发送最小必要响应头:
header('Content-Encoding: none')+header('Connection: close')(可选但推荐) - 每次输出后必须连续调用
echo str_repeat(' ', 256)(填充空白防某些浏览器不触发渲染)+flush()+ob_flush()
为什么flush()单独调用无效
flush()只刷新PHP的“系统输出缓冲”,不处理PHP自身的输出缓冲(ob_*系列)或Web服务器缓冲。如果ob_start()被隐式触发(比如某些框架或php.ini里output_buffering=4096),flush()完全不起作用。
典型失效场景:本地Apache可能表现正常,但上线到Nginx + PHP-FPM环境就卡住——因为Nginx默认开启fastcgi_buffering on,会攒够8KB才转发给浏览器。
立即学习“PHP免费学习笔记(深入)”;
- PHP-FPM配置需设
fastcgi_buffering off(或在Nginx的location块中加fastcgi_buffering off) - 若无法改服务器配置,可用
ignore_user_abort(true)配合长循环+定时sleep(),靠超时强制断连来“模拟”结束 - Chrome对小数据包更敏感,建议每次输出至少含换行符
"\n"和256字节填充,否则可能不渲染
如何安全标记实时输出结束
没有HTTP标准的“流结束标记”,所谓“结束标识”其实是让浏览器主动停止等待。最可靠方式不是发一个特殊字符串,而是让服务端真正关闭连接,同时前端监听load或readystatechange事件做判断。
常见误区是用echo "[DONE]"; flush(); die();——这并不能保证浏览器立刻收到并解析该字符串,尤其当它被截断在TCP包中间时。
- 服务端结束前,先输出足够长度的内容(如1MB空格),再
echo "END"+flush()+ob_flush()+fclose(STDOUT)(PHP 7.4+) - 更稳妥的做法是:设置
header('X-Accel-Buffering: no')(针对Nginx)或header('Cache-Control: no-cache'),避免代理缓存干扰 - 前端用
fetch()配合ReadableStream逐块读取,检测到末尾字符串(如"[FIN]")即break,而非依赖response.body.getReader().read()返回{done: true}
真实项目中容易被忽略的兼容点
开发时用php -S跑本地服务一切正常,一上生产环境就失效——八成是反向代理或CDN在作祟。Cloudflare、阿里云WAF、甚至部分HTTPS卸载设备都会强制缓冲响应体,且不尊重Connection: close头。
另一个隐藏坑是PHP版本差异:ob_flush()在PHP 8.0+对CLI SAPI行为有变更,而fastcgi_finish_request()虽能提前结束请求但会丢弃后续输出,不能用于“边输出边结束”的场景。
- 务必在目标环境执行
phpinfo()确认output_buffering、zlib.output_compression、implicit_flush三项值均为Off - 用
curl -v http://yoursite/stream.php直接看原始响应头和分块传输情况,比浏览器开发者工具更可信 - 移动端Safari对
text/event-stream支持有限,若需强实时,优先考虑WebSocket而非纯PHP流输出











