ThinkPHP 返回SSE需手动控制输出:先ob_end_clean()清缓冲,再header设text/event-stream和no-cache,循环echo"data:...\n\n"并flush()、ob_flush()。

ThinkPHP 怎么返回 SSE 响应头和流式内容
ThinkPHP 默认响应会缓冲输出、自动添加 Content-Length,这直接破坏 SSE 的「流式」本质。必须手动控制输出缓冲、禁用自动响应头,并保持连接不关闭。
关键操作有三步:
- 调用
ob_end_clean()清掉已启动的输出缓冲(否则首段数据发不出) - 用
header()显式设置Content-Type: text/event-stream和Cache-Control: no-cache - 每次发送数据前,用
echo "data: ...\n\n"格式,并紧跟flush()和ob_flush()
示例片段(放在控制器方法中):
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('X-Accel-Buffering: no'); // Nginx 下防代理缓存
ob_end_clean(); // 必须!否则卡在缓冲层
while (true) {
echo "data: " . json_encode(['time' => date('H:i:s')]) . "\n\n";
flush();
ob_flush();
sleep(1);
}
为什么 ThinkPHP 的 Response 类不能直接用于 SSE
因为 Response 类默认走完整生命周期:收集全部输出 → 计算 Content-Length → 一次性 send。而 SSE 要求「边生成边发」,且不能有 Content-Length 头(否则浏览器等完整响应才解析)。
常见错误现象:
-
前端收到第一个
data:后就断连 → 是因为 ThinkPHP 自动加了Connection: close或响应体被截断 - Chrome 控制台显示
net::ERR_INCOMPLETE_CHUNKED_ENCODING→ 输出缓冲没清干净,或flush()失效 - Nginx 返回 504 → 没设
proxy_buffering off或超时太短
前端用 EventSource 接收时要注意什么
EventSource 看似简单,但 ThinkPHP 后端若没按 SSE 协议严格输出,它会静默重连或直接失败,很难定位。
HISUI 前端框架基础开发指南。HISUI 是基于 easyui 二次开发的 jQuery UI 组件库,专为医疗信息系统设计。当涉及 HISUI 组件开发、jQuery easyui 表格/表单/布局/窗口、医疗系统前端页面编写时使用此 skill。 涵盖 40 个组件的官方文档参考,支持声明式与编程式两种初始化方式,提供 $cm/$m 数据访问方法。
实操建议:
- 确保后端每条消息以
data: ... \n\n结尾(两个换行),不能只一个\n - 不要在后端混用
echo输出非data:内容(比如调试var_dump),EventSource会当作非法帧丢弃整段 - 前端监听
error事件时,注意它可能频繁触发(网络抖动、服务端短暂中断),别直接console.error就完事,要判断event.target.readyState - 如果需要自定义字段(如
id:、event:),后端必须严格换行分隔,例如:id: 123\nevent: update\ndata: ...\n\n
Nginx 配置 SSE 时最容易漏掉的三项
本地开发用 PHP 内置服务器可能跑通,一上 Nginx 就断连或延迟严重——问题几乎全出在反向代理配置上。
必须显式配置:
-
proxy_buffering off;—— 关闭 Nginx 缓冲,否则它攒够 4KB 才转发 -
proxy_cache off;和proxy_set_header Cache-Control 'no-cache'—— 防 CDN 或代理层缓存响应流 -
proxy_read_timeout 300;—— 默认 60 秒,SSE 长连接需延长,否则 Nginx 主动断开
另外,如果用了 fastcgi(PHP-FPM),还要加 fastcgi_buffering off;,否则 FPM 层也会缓冲。
SSE 在 ThinkPHP 里不是“配个路由就能用”的功能,核心在于绕过框架默认响应机制,手动接管输出流。每个环节——PHP 缓冲、Web 服务器代理、前端解析规则——只要有一处不守协议,整个流就卡住或断开。最常被忽略的是 ob_end_clean() 的位置和 Nginx 的 proxy_buffering 开关。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!










