uni.request 请求流文件必须设 responseType: 'arraybuffer',否则会乱码或报错;小程序需 writeFile 写入临时文件再 openDocument,H5 用 Blob + createObjectURL。

uni.request 必须设 responseType: 'arraybuffer'
默认情况下 uni.request 把响应当文本或 JSON 解析,遇到 PDF、Excel、图片等流文件会直接乱码或报错 Failed to execute 'arrayBuffer' on 'Response': body stream is locked。这不是后端问题,是前端没告诉 UniApp “我要接的是二进制”。
必须显式设置 responseType: 'arraybuffer',否则 res.data 是字符串或空对象,后续所有转换都失效。
- 不要写成
'blob'—— UniApp 不支持该值,会静默降级为 text - H5、微信小程序、App 三端都认
'arraybuffer',无需条件判断 - 如果接口需要鉴权,
header中的 token 要照常传,不影响二进制接收
微信小程序预览流文件:用 writeFile + openDocument
小程序不支持 Blob 或 URL.createObjectURL,也不能直接用 base64 打开 PDF/Excel。唯一可靠路径是:把 ArrayBuffer 写入本地临时文件,再调 uni.openDocument。
关键点在于写入时的 encoding: 'binary' 和路径必须用 uni.env.USER_DATA_PATH:
-
filePath必须带扩展名(如.pdf),否则openDocument无法识别类型 -
data字段直接填res.data(即原始 ArrayBuffer),不要先转 base64 再转回来 -
uni.openDocument的fileType参数可选填,但建议显式写上('pdf'、'xlsx')
H5 端可以直接用 URL.createObjectURL(new Blob([...]))
H5 浏览器支持 Blob 和 Object URL,比小程序灵活得多。但注意:不能直接把 ArrayBuffer 丢给 Blob 构造函数,要包一层数组。
正确写法是:new Blob([res.data], { type: 'application/pdf' }) —— 方括号不能少,否则报错 TypeError: Failed to construct 'Blob'。
-
type值要尽量准确,PDF 用'application/pdf',Excel 用'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' - 生成的 URL 是临时的,页面刷新即失效,不用手动 revoke(除非长时驻留)
- 别在 App 或小程序里套用这段代码,会直接报
Blob is not defined
大文件(>5MB)要避免 uni.arrayBufferToBase64
uni.arrayBufferToBase64 看起来方便,但它会把整个 ArrayBuffer 拷贝进字符串,内存占用翻倍,10MB 文件可能触发 iOS 小程序的内存警告甚至白屏。
真正需要 base64 的场景极少(比如内联图片 src)。绝大多数情况应绕过它:
- 小程序:走
writeFile,跳过 base64 环节 - H5:走
Blob+createObjectURL,也无需 base64 - 只有在必须传 base64 给第三方 SDK 或服务时,才用它,且要加 loading 提示和失败兜底
流文件处理最易被忽略的一点:不同端的“临时文件”生命周期完全不同。小程序的 USER_DATA_PATH 文件能存到进程退出,而 H5 的 Blob URL 页面刷新就丢——别假设一次转换能跨端复用。











