🚀 Blob、File、FileReader、ArrayBuffer、Base64、URL.createObjectURL()的区别
欢迎来到我的博客文章!所有文章都是满满的前端干货,文章简明扼要。
一、核心概念对比
| 概念 | 本质 | 用途 | 特点 |
| Blob | 二进制大对象 | 存储/传输二进制数据 | 不可变、有type和size、可切片 |
| File | Blob的子类 | 表示用户选择的文件 | 额外有name、lastModified等文件元信息 |
| ArrayBuffer | 原始二进制缓冲区 | 底层数据存储 | 不能直接操作,需通过TypedArray或DataView |
| Base64 | 编码格式(字符串) | 数据嵌入、传输 | 体积增大约33%,纯文本便于传输 |
| FileReader | API工具类 | 读取Blob/File内容 | 异步、支持多种读取方式 |
| URL.createObjectURL() | API方法 | 生成临时URL | 同步、需手动revokeObjectURL()释放 |
二、关系图谱
ArrayBuffer (底层数据)
↑
| 通过TypedArray/DataView操作
|
Blob ───┐
↑ │ 有type/size
| │ 可切片
| ↓
File (继承Blob,增加name/lastModified)
│
├─→ FileReader (异步读取内容)
│ ├─ readAsArrayBuffer()
│ ├─ readAsDataURL() → Base64
│ ├─ readAsText()
│ └─ readAsBinaryString()
│
└─→ URL.createObjectURL() (同步生成临时URL)
三、代码示例对比
Blob vs File
const blob = new Blob(['Hello'], { type: 'text/plain' });
console.log(blob.type);
console.log(blob.size);
const file = new File(['World'], 'test.txt', { type: 'text/plain' });
console.log(file.type);
console.log(file.size);
console.log(file.name);
console.log(file.lastModified);
FileReader 读取方式对比
const fileInput = document.querySelector('input[type="file"]');
fileInput.addEventListener('change', (e) => {
const file = e.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
console.log(reader.result);
document.querySelector('img').src = reader.result;
};
reader.readAsArrayBuffer(file);
reader.onload = () => {
const buffer = reader.result;
const uint8 = new Uint8Array(buffer);
console.log(uint8);
};
reader.readAsText(file, 'utf-8');
reader.onload = () => {
console.log(reader.result);
};
});
URL.createObjectURL() vs FileReader(图片预览)
const file = e.target.files[0];
const url1 = URL.createObjectURL(file);
img.src = url1;
img.onload = () => URL.revokeObjectURL(url1);
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
img.src = reader.result;
};
| 对比项 | createObjectURL() | FileReader.readAsDataURL() |
| 速度 | ⚡ 同步,立即返回 | 🐌 异步,需等待 |
| 内存 | 🔗 引用原Blob | 📦 复制一份Base64 |
| URL长度 | 短(blob:http://...) | 长(含完整Base64) |
| 释放 | 需手动revokeObjectURL() | 自动 |
| 适用场景 | 图片/视频预览 | 需Base64的场景(如上传到某些API) |
四、实际应用场景
📸 图片上传前预览
<input type="file" accept="image/*" id="fileInput">
<img id="preview" style="max-width: 300px;">
<script>
document.getElementById('fileInput').addEventListener('change', (e) => {
const file = e.target.files[0];
const url = URL.createObjectURL(file);
preview.src = url;
preview.onload = () => URL.revokeObjectURL(url);
});
</script>
📤 文件上传(FormData + Blob)
const file = e.target.files[0];
const formData = new FormData();
formData.append('file', file, file.name);
fetch('/upload', {
method: 'POST',
body: formData
});
const chunk = file.slice(0, 1024 * 1024);
formData.append('chunk', chunk);
🎨 Canvas导出图片
const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');
canvas.toBlob((blob) => {
const url = URL.createObjectURL(blob);
const img = document.createElement('img');
img.src = url;
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = () => {
console.log(reader.result);
};
}, 'image/png', 0.9);
五、快速决策表
| 需求 | 推荐方案 |
| 图片/视频预览 | URL.createObjectURL() |
| 上传到后端 | FormData.append(file) |
| 需要Base64字符串 | FileReader.readAsDataURL() |
| 二进制数据处理 | FileReader.readAsArrayBuffer() |
| 大文件分片上传 | Blob.slice() |
| 文件元信息(名/时间) | 用File而非Blob |
六、注意事项
⚠️ createObjectURL() 必须释放,否则内存泄漏
const url = URL.createObjectURL(file);
img.src = url;
img.onload = () => URL.revokeObjectURL(url);
⚠️ Base64体积更大
1MB文件 → 约1.33MB Base64,慎用于大文件
⚠️ FileReader是异步的,不能直接return结果
function read(file) {
const reader = new FileReader();
reader.readAsDataURL(file);
return reader.result;
}
function read(file) {
return new Promise((resolve) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.readAsDataURL(file);
});
}
核心要点总结
💡 关键知识点
- Blob:二进制大对象,不可变,有type和size
- File:继承Blob,额外有name和lastModified
- ArrayBuffer:底层二进制缓冲区,需通过TypedArray操作
- Base64:编码格式,体积增大33%,便于传输
- FileReader:异步读取Blob/File内容
- URL.createObjectURL():同步生成临时URL,需手动释放