一文了解 Blob 文件格式:前端必备技能之一(2026 年最新视角)
在现代前端开发中,Blob 是处理二进制数据的基石,几乎所有涉及文件、图片、视频、音频、下载、上传、分片、Canvas/WebGL 输出、MediaSource 等场景都离不开它。
很多人把 Blob 当成“文件格式”,其实它不是一种具体的文件格式(如 .png、.pdf、.mp4),而是一种浏览器原生提供的二进制数据抽象。
1. Blob 到底是什么?
官方定义(MDN 2025–2026 最新版):
Blob 对象表示一个不可变、原始的类文件二进制数据对象。
它的数据可以是文本或二进制格式读取,也可以转为 ReadableStream 处理。
关键特性总结:
| 特性 | 说明 | 意义(为什么重要) |
|---|---|---|
| 不可变 | 一旦创建,内容不可修改(类似字符串) | 线程安全、可靠分片、缓存友好 |
| 原始二进制 | 不一定是 JS 可直接理解的格式(可以是任何字节序列) | 能承载图片、视频、PDF、Excel、zip 等一切 |
| 类文件 | 有 size、type 属性,像文件但不一定是真实磁盘文件 | 统一处理用户上传文件 + 程序生成数据 |
| 内存驻留 | 默认存在内存中(非磁盘) | 适合临时处理、大文件分片、不落盘场景 |
| 支持 slice | 可高效切片(不复制数据,只改引用) | 大文件分片上传的核心实现方式 |
Blob ≠ File(最容易混淆的点)
- Blob:纯二进制 + size + type
- File:继承自 Blob + name + lastModified(文件元信息)
// File 就是带名字的 Blob
const file = new File(["内容"], "avatar.jpg", { type: "image/jpeg" });
// 等价于
const blob = new Blob(["内容"], { type: "image/jpeg" });
2. Blob 的创建方式(最常用 5 种)
// 1. 最常用 - 从字符串 / ArrayBuffer / 其他 Blob 创建
const blob1 = new Blob(["Hello 重阳"], { type: "text/plain" });
const blob2 = new Blob([new Uint8Array([0x48, 0x65, 0x6c, 0x6c, 0x6f])]); // "Hello"
// 2. 从 Canvas 导出图片
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d");
// ... 画图 ...
const blobFromCanvas = await new Promise(resolve => {
canvas.toBlob(resolve, "image/webp", 0.85);
});
// 3. 从 fetch / XMLHttpRequest 响应创建
const response = await fetch("https://example.com/image.jpg");
const blobFromNetwork = await response.blob();
// 4. 从 input[type=file] 获取(最常见用户上传)
input.addEventListener("change", e => {
const file = e.target.files[0]; // File 对象
const blob = file; // File 就是 Blob
});
// 5. 合并多个 Blob(常用于分片上传后合成)
const finalBlob = new Blob([part1, part2, part3], { type: "video/mp4" });
3. Blob 的核心方法 & 属性(实战必背)
| 属性/方法 | 返回值类型 | 作用 & 经典用法 |
|---|---|---|
blob.size | number | 数据字节大小(常用于进度条、校验) |
blob.type | string | MIME 类型(如 “image/png”、”application/pdf”) |
blob.slice(start?, end?, type?) | Blob | 零拷贝切片(分片上传神器) |
blob.arrayBuffer() | Promise | 转为 ArrayBuffer(常用于加密、WebAssembly) |
blob.text() | Promise | 转为 UTF-8 字符串(常用于文本文件) |
blob.stream() | ReadableStream | 转为流(配合 fetch、MediaSource、视频播放) |
4. 经典实战场景(直接复制可用)
4.1 文件下载(最常用写法)
function downloadBlob(blob, filename = "download") {
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url); // 重要!及时释放内存
}
// 示例:下载文本
const textBlob = new Blob(["前端重阳666"], { type: "text/plain" });
downloadBlob(textBlob, "hello.txt");
// 示例:下载图片
canvas.toBlob(blob => downloadBlob(blob, "screenshot.png"), "image/png");
4.2 大文件分片上传(面试/大厂高频)
async function uploadLargeFile(file, chunkSize = 5 * 1024 * 1024) { // 5MB
const chunks = [];
let start = 0;
while (start < file.size) {
const chunk = file.slice(start, start + chunkSize);
chunks.push(chunk);
start += chunkSize;
}
// 并发上传(可加控制并发数)
await Promise.all(chunks.map(async (chunk, index) => {
const formData = new FormData();
formData.append("chunk", chunk);
formData.append("index", index);
formData.append("total", chunks.length);
formData.append("filename", file.name);
await fetch("/api/upload/chunk", { method: "POST", body: formData });
}));
// 通知服务端合并
await fetch("/api/upload/merge", {
method: "POST",
body: JSON.stringify({ filename: file.name, chunks: chunks.length })
});
}
4.3 图片预览(零后端)
imgInput.addEventListener("change", e => {
const file = e.target.files[0];
if (file?.type.startsWith("image/")) {
preview.src = URL.createObjectURL(file);
// 使用完记得 revoke
preview.onload = () => URL.revokeObjectURL(preview.src);
}
});
5. 常见面试/高频问题速记
- Blob 和 ArrayBuffer 的区别?
Blob:不可变、带 type、支持 slice 零拷贝、适合文件级操作
ArrayBuffer:纯二进制缓冲区、可修改、适合底层字节操作 - 为什么分片上传用 Blob.slice 而不用 new Blob([部分数据])?
slice 是零拷贝(只改指针),后者会复制数据,内存爆炸 - URL.createObjectURL(blob) 产生的 url 是什么?
blob: 协议的临时 URL,只在当前文档生命周期有效,使用完要 revoke - 大文件预览/播放不卡顿的原理?
blob.slice → stream → MediaSource / video.src = URL.createObjectURL
总结一句话
Blob 是前端处理一切“非结构化二进制数据”的统一入口
掌握 Blob = 掌握了文件上传/下载、分片、预览、流式处理、Canvas/WebRTC 输出等 80% 的二进制场景。
重阳,你现在最常在哪些场景用到 Blob?
是文件分片上传、图片压缩预览、视频流处理,还是其他?
或者你遇到过 Blob 相关的坑(内存泄漏、type 不对、切片后丢失等),可以聊聊,我们一起拆解~