
本文详解如何在 Flask 应用中正确实现 Server-Sent Events(SSE),重点解决 EventSource 无法接收流数据的常见问题——核心在于响应数据必须严格遵循 data:xxx\n\n 格式,且需设置正确的 MIME 类型。
本文详解如何在 flask 应用中正确实现 server-sent events(sse),重点解决 eventsource 无法接收流数据的常见问题——核心在于响应数据必须严格遵循 data:xxx\n\n 格式,且需设置正确的 mime 类型。
在 Flask 中通过 SSE 实现实时文本流传输,关键不在于路由逻辑或前端调用方式,而在于服务端生成的数据格式是否符合 W3C EventSource 规范。即使后端返回了 Response 对象、前端正确初始化了 EventSource,只要每条消息缺失 data: 前缀或缺少结尾的双换行符(\n\n),浏览器就会静默忽略该消息——这正是多数开发者遇到“流无反应”问题的根本原因。
✅ 正确的 SSE 响应格式要求
根据规范,每个事件消息必须满足以下结构:
data: Hello, world! data: This is line two.
- 每行以
data:开头(注意冒号后有一个空格); - 多行
data:可组成一条完整消息(浏览器会自动拼接); - 消息之间必须用 两个连续换行符
\n\n分隔; - 可选支持
id:、event:、retry:等字段,但data:是必需的; - 响应头
Content-Type必须为text/event-stream,且禁止关闭连接(Flask 默认不缓冲,但需确保无中间件强制结束流)。
? Flask 后端修正示例
以下是符合规范的 /stream 路由实现:
from flask import Flask, request, Response
import time
app = Flask(__name__)
@app.route('/stream', methods=['POST'])
def stream():
# 接收 POST 数据(如表单字段)
user_input = request.form.get('data', 'default')
def event_stream():
for i in range(5):
# ✅ 严格遵循 SSE 格式:data: + 内容 + \n\n
yield f"data: Processing step {i+1} for '{user_input}'\n\n"
time.sleep(1) # 模拟耗时操作
yield "data: Stream completed.\n\n"
return Response(
event_stream(),
content_type='text/event-stream',
headers={
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
}
)
⚠️ 注意事项:
- 不要使用
return jsonify(...)或普通字符串响应,必须返回Response流;- 避免在生成器中抛出未捕获异常,否则流会中断;
- 若需传递结构化数据(如 JSON),请编码为字符串并包裹在
data:中:yield f"data: {{\"step\": {i}, \"status\": \"ok\"}}\n\n"
? 前端 EventSource 集成(index.html)
确保 index.html 中的 JavaScript 正确监听并渲染:
FastAPI + Flask 混合部署最佳实践,解决路由定义、API 代理等常见问题,适用于同时运行 FastAPI API 与 Flask 前端的场景。
<div id="events"></div>
<script>
if (window.EventSource) {
// ❗发起的是 GET 请求(SSE 协议限制),无需 POST
const source = new EventSource('/stream');
source.onmessage = function(event) {
const div = document.createElement('div');
div.textContent = event.data; // 自动去除 data: 前缀并合并多行
document.getElementById('events').appendChild(div);
};
source.addEventListener('open', () => {
console.log('SSE connection established');
});
source.onerror = function(err) {
console.error('EventSource error:', err);
// 可在此添加重连逻辑
};
} else {
console.error('Your browser does not support Server-Sent Events.');
}
</script>
? 关键说明:
EventSource仅支持 GET 请求,因此/stream路由应通过POST接收初始参数(如stream_page.html表单提交),但实际流连接必须由index.html用GET发起;- 若需动态传参(如用户输入),推荐方案是:
①stream_page.html提交表单至后端,将参数存入 session/缓存/数据库;
②index.html的EventSource发起 GET/stream,后端从存储中读取参数并启动流;
或更简洁地:index.html通过 URL 查询参数传递(如/stream?data=xxx),后端用request.args.get()获取。
✅ 总结
成功实现 Flask SSE 的三大支柱:
-
格式合规:每条
yield必须是f"data:{content}\n\n"; -
响应正确:
Response(..., content_type='text/event-stream'); -
前端匹配:
EventSource使用 GET 连接,并正确处理onmessage。
只要守住这三点,即可让实时日志、进度更新、通知推送等场景在 index.html 中平滑呈现,无需轮询或 WebSocket 复杂性。










