前端JS接收二进制流字符串 如何保存未知类型文件不损坏
问题根因
- 你当前拿到的
response.body是被JavaScript按照UTF-8编码规则解码后的字符串,二进制文件中大量不符合UTF-8编码规则的字节会被自动替换为�这类乱码占位符,原始二进制数据已经被不可逆破坏,仅纯文本类内容因为没有非法UTF-8字节可以正常打开。 - PowerShell转换正常是因为它直接操作原始二进制字节,没有经过JS的字符串编码转换步骤,数据没有被篡改。
解决方案
方案1(推荐):请求阶段直接获取二进制数据
不要让HTTP客户端将返回结果解析为字符串,直接获取Blob/ArrayBuffer格式的原始二进制数据:
基于fetch的示例:
fetch('/你的接口地址', { method: 'GET' }).then(async res => { // 直接调用blob()获取二进制对象,不要调用text()/json() const blob = await res.blob() // 从响应头取文件名,或者用你接口返回的文件名 const filename = response.filename const blobURL = window.URL.createObjectURL(blob) downloadAnchor.current.href = blobURL downloadAnchor.current.download = filename downloadAnchor.current.click() // 用完释放内存,避免内存泄漏 window.URL.revokeObjectURL(blobURL) })
基于axios的示例:
请求配置中添加responseType: 'blob'参数,强制返回二进制数据:
axios.get('/你的接口地址', { responseType: 'blob' // 核心配置,不能省略 }).then(res => { const blob = res.data const filename = response.filename // 后续下载逻辑同上 })
方案2(兼容场景):手动还原被转成字符串的二进制数据
如果业务场景限制只能拿到已经被转成字符串的二进制内容,使用Latin-1编码规则将字符串还原为原始字节:
const binaryStr = response.body // 将字符串按单字节编码还原为二进制数组 const uint8Array = new Uint8Array(binaryStr.length) for (let i = 0; i < binaryStr.length; i++) { uint8Array[i] = binaryStr.charCodeAt(i) & 0xff } const blob = new Blob([uint8Array], { type: 'application/octet-stream' }) // 后续下载逻辑同上
额外注意点
你原代码中downloadAnchor!.current!.download = 'filename';写死了字符串filename,需要改成实际的文件名变量download = filename,否则下载的文件会被命名为filename无后缀。
内容的提问来源于stack exchange,提问作者Tellon
相关产品推荐
相关产品推荐

