SSE仅支持UTF-8文本,不支持二进制流;EventSource强制解析为字符串,遇非UTF-8字节即报错断连;需改用fetch+ReadableStream处理二进制,或Base64编码嵌入data字段。

SSE(Server-Sent Events)本身不支持二进制流,它只定义在 text/event-stream MIME 类型下传输 UTF-8 编码的纯文本事件。所谓“HTTP 二进制流 + SSE”本质上是概念冲突——浏览器的 EventSource API 无法解析或接收二进制数据,遇到非文本内容会直接报错或中断连接。
为什么 EventSource 无法处理二进制数据
EventSource 是一个只读、单向、基于文本的流式通信接口,底层强制将响应体按 UTF-8 字节流解析为字符串,并按 data:、event:、id:、retry: 等字段分割和解码。一旦服务端返回非 UTF-8 兼容字节(如图片、音频、Protobuf 序列化数据),JS 引擎会触发 error 事件,连接关闭,且无法访问原始响应体。
替代方案:用 Fetch + ReadableStream 处理二进制流
若后端实际发送的是二进制流(即使设置了 text/event-stream),应放弃 EventSource,改用 fetch() 获取 Response.body,再通过 ReadableStream 逐段读取:
- 设置请求头
Accept: text/event-stream(仅作语义提示,不影响二进制传输) - 用
response.body.getReader()获取流读取器 - 调用
reader.read()获取{ done, value },其中value是Uint8Array - 自行定义分帧规则(如按长度前缀、特殊分隔符或固定包结构)来还原消息
服务端需明确区分协议类型
不要混用 SSE 协议与二进制语义。正确做法是:
立即学习“Java免费学习笔记(深入)”;
- 真要发事件 → 服务端严格输出 UTF-8 文本,每条以
data: ...\n\n结尾,MIME 设为text/event-stream - 真要发二进制 → 改用普通 HTTP 流(如
application/octet-stream)或 WebSocket,前端用fetch + ReadableStream或WebSocket.binaryType = 'arraybuffer' - 若需混合文本事件 + 二进制载荷,可将二进制 Base64 编码后放入
data:字段(适合小数据,有约 33% 体积开销)
常见误判场景与检查建议
有时开发者看到响应头含 Content-Type: text/event-stream 就默认是 SSE,但实际可能是服务端错误配置或调试代理篡改了内容。建议:
- 用浏览器 DevTools 的 Network → Response 查看原始响应体是否为可读文本
- 监听
eventsource.onerror并打印eventsource.readyState判断是否因编码问题断连 - 服务端开启日志,确认输出是否真的写入了合法 SSE 格式(含换行、冒号、双换行)
不复杂但容易忽略:SSE 是文本协议,不是通用流通道。选对传输方式,比强行解析更重要。


















