response.blob() 返回的是 blob 对象,它是浏览器原生的不可变二进制数据容器,支持惰性加载与分片读取,需通过 url.createobjecturl() 或 arraybuffer()/text() 等方法进一步处理。

response.blob() 返回的是什么类型的数据
response.blob() 返回的是一个 Blob 对象,不是 ArrayBuffer,也不是 Uint8Array —— 它是浏览器原生的二进制数据容器,惰性加载、不可变、支持分片读取。你不能直接用 JSON.parse() 或 text() 处理它,否则会报错 TypeError: Failed to execute 'json' on 'Response': body stream is locked(因为流已被消费)。
常见误操作:在调用 response.blob() 前先调用了 response.text() 或 response.json(),导致流关闭,后续再调 blob() 会返回空 Blob 或抛异常。
- ✅ 正确顺序:只调一次
response.blob(),或根据需要选text()/json()/arrayBuffer()中的一个 - ⚠️ 注意:
Blob对象本身不包含文件名、MIME 类型等元信息,这些需从response.headers.get('content-type')和response.url或后端响应头中手动提取 - ?
Blob.size和Blob.type是只读属性,可用于校验(比如下载图片时检查type是否为image/png)
怎么把 blob 转成可下载的文件链接
最常用场景是「后端返回 PDF/Excel/ZIP 文件流,前端触发下载」。核心是用 URL.createObjectURL() 创建临时 URL,再用 <a download></a> 触发保存。
关键点:必须在下载完成后立即调用 URL.revokeObjectURL(),否则内存泄漏(尤其在频繁下载时)。
fetch('/api/report.pdf')
.then(res => {
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const filename = 'report.pdf';
return res.blob().then(blob => ({
blob,
filename,
type: res.headers.get('content-type') || 'application/octet-stream'
}));
})
.then(({ blob, filename, type }) => {
const url = URL.createObjectURL(new Blob([blob], { type }));
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url); // 必须调用
});
- ⚠️ 如果后端没返回
Content-Disposition: attachment; filename="xxx",你得自己约定文件名,或从 URL 路径解析(如new URL(res.url).pathname.split('/').pop()) - ⚠️
new Blob([blob], { type })这步看似多余,但某些浏览器(如旧版 Safari)对原始 blob 的 MIME 类型识别不准,显式包裹可提升兼容性 - ? 下载大文件(>100MB)时,
createObjectURL仍会占用内存;更优方案是用ReadableStream+stream.pipeTo()(需现代浏览器支持)
怎么读取 blob 内容做校验或预览
如果要校验文件内容(比如检查 PNG 签名)、生成缩略图、或解析 Excel 表格,就不能只下载,得把 blob 转成可处理的格式。
常用转换方式:
-
blob.arrayBuffer()→ 得到ArrayBuffer,适合底层解析(如用jszip解压、用pdfjs-dist渲染 PDF) -
blob.text()→ 仅适用于 UTF-8 文本类 blob(如 CSV、JSON 配置),注意编码错误风险 -
URL.createObjectURL(blob)→ 直接用于<img src>、<video src></video>、<iframe src></iframe>预览(无需转码)
例如预览图片:
res.blob().then(blob => {
const img = document.querySelector('#preview');
img.src = URL.createObjectURL(blob);
img.onload = () => URL.revokeObjectURL(img.src); // 预览完就释放
});
再比如校验 PNG 文件头(前 8 字节应为 89 50 4E 47 0D 0A 1A 0A):
blob.arrayBuffer().then(buf => {
const view = new Uint8Array(buf, 0, 8);
const isPng = view[0] === 0x89 && view[1] === 0x50 && view[2] === 0x4E && view[3] === 0x47;
console.log('is PNG:', isPng);
});
fetch blob 响应的常见错误和绕过技巧
实际项目中常遇到 CORS、跨域 Blob 无法预览、Safari 下 download 失效等问题,本质不是 blob() 方法的问题,而是响应头或浏览器策略限制。
- ❌ 错误现象:
Failed to execute 'createObjectURL' on 'URL': Overload resolution failed→ 通常是因为传入了 null/undefined,检查res.ok和网络是否真的返回了 blob - ❌ 错误现象:图片
<img>显示空白,控制台报Cross-Origin Read Blocking (CORB)→ 后端未设置Access-Control-Allow-Origin或Content-Type不匹配(如返回text/plain却当图片用) - ✅ 绕过 CORB:服务端响应头加
crossorigin="anonymous"并确保Access-Control-Allow-Origin: *(或具体域名),且 fetch 时带上mode: 'cors' - ✅ Safari 下
a.download失效:改用location.href = url(但会跳转页面),或用document.execCommand('saveAs')(已废弃,仅作兼容兜底) - ⚠️ 注意:
response.blob()不会自动解压 gzip,压缩由浏览器透明处理,你拿到的 blob 已是解压后数据
真正容易被忽略的是:Blob 的生命周期完全独立于 fetch 请求,即使请求已结束,只要没调 revokeObjectURL,它就一直驻留在内存里——尤其是单页应用中反复下载又忘记清理,几 MB 的 PDF 就可能吃掉几百 MB 内存。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











