根本原因是websocket协议支持文本和二进制两种帧类型,服务端发送二进制帧(如通过sendbinary、binarymessage或未tostring的buffer)时,客户端必收blob;binarytype仅控制二进制帧的解析形式,无法改变已发送帧类型。

WebSocket 收到 event.data 是 [object Blob] 的根本原因
不是前端写错了,也不是服务器“发错了”,而是 WebSocket 协议本身允许两种基础数据类型:文本(string)和二进制(Blob、ArrayBuffer)。浏览器收到什么,取决于服务端发送时用的是文本帧还是二进制帧——而这个决定权在服务端的 send() 调用方式上。
常见误判是:“我传的是字符串,它就该是文本”。但实际中,如果服务端把字符串转成了 Buffer、Uint8Array 或直接调用了 sendBinary()(比如 Java 的 sendBinary()、.NET 的 SendAsync(..., WebSocketMessageType.Binary)),那客户端收到的就是 Blob,哪怕内容本身是纯文本。
binaryType 设置不能改变已发送的数据类型
ws.binaryType = 'blob' 或 'arraybuffer' 只影响浏览器如何“解释”接收到的二进制帧,它不会把文本帧变成 Blob,也不会把二进制帧“变回”字符串。如果你看到 [object Blob],说明服务端确实发了二进制帧,此时设置 binaryType 只是选包装形式,不是纠错手段。
-
ws.binaryType = 'blob'→event.data是Blob实例(默认值) -
ws.binaryType = 'arraybuffer'→event.data是ArrayBuffer(需手动new TextDecoder().decode()) - 无论设成啥,对文本帧都无影响:
event.data始终是string
如何安全地处理不确定类型的 event.data
不要假设类型,每次都要检查。最简健壮写法是:
PigX UI Pro 前端开发指南 - Vue 3 + TypeScript + Element Plus。当用户提到 PigX UI、PigX 前端、lgb-mgui 项目、Vue 3 企业级后台开发、Element Plus 后台开发时使用此技能。
socket.onmessage = (event) => {
if (typeof event.data === 'string') {
addLog(`⬅️ 收到文本: ${event.data}`);
} else if (event.data instanceof Blob) {
event.data.text().then(text => addLog(`⬅️ 收到文本(Blob): ${text}`));
} else if (event.data instanceof ArrayBuffer) {
const text = new TextDecoder().decode(event.data);
addLog(`⬅️ 收到文本(ArrayBuffer): ${text}`);
}
};
注意:Blob.text() 是异步的,别用 FileReader 同步读取——它更重、更易出错,且不支持 async/await 流式处理。
后端发文本却收 Blob?先查这三处
即使你确认后端代码写的是 send("hello"),仍可能因以下原因被当成二进制帧:
- Node.js
ws库:若接收上游消息时是Buffer(比如从另一个 WebSocket 或 TCP 流来),又没显式.toString()就直接ws.send(buffer),就会发二进制帧 - .NET Core
WebSocket:调用SendAsync(..., WebSocketMessageType.Text)才是文本;若误用WebSocketMessageType.Binary,哪怕内容是 UTF-8 字节数组,前端也收Blob - Java Spring WebSocket:
TextMessage对应文本帧,BinaryMessage对应二进制帧——类型写错就全错
真正关键的不是“内容是不是文本”,而是“服务端构造消息时用的协议帧类型”。这点容易被忽略,但决定了前端第一眼看到的是 string 还是 [object Blob]。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










