🚀 Blob、File、FileReader、ArrayBuffer、Base64、URL.createObjectURL()的区别

📅 发布于 2026年2月 | 👤 作者:博主 | 🏷️ 标签:Blob, File, FileReader, ArrayBuffer, Base64, URL.createObjectURL, Web开发, 前端, 面试

欢迎来到我的博客文章!所有文章都是满满的前端干货,文章简明扼要。

一、核心概念对比

概念 本质 用途 特点
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

// Blob:只有type和size
const blob = new Blob(['Hello'], { type: 'text/plain' });
console.log(blob.type);    // "text/plain"
console.log(blob.size);    // 5
// ❌ blob.name 不存在

// File:继承Blob + 文件信息
const file = new File(['World'], 'test.txt', { type: 'text/plain' });
console.log(file.type);         // "text/plain"
console.log(file.size);         // 5
console.log(file.name);         // "test.txt" ✅
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();

  // 方式1:读为Base64(常用于图片预览)
  reader.readAsDataURL(file);
  reader.onload = () => {
    console.log(reader.result); // "data:image/png;base64,iVBORw0KG..."
    document.querySelector('img').src = reader.result;
  };

  // 方式2:读为ArrayBuffer(用于二进制处理)
  reader.readAsArrayBuffer(file);
  reader.onload = () => {
    const buffer = reader.result; // ArrayBuffer
    const uint8 = new Uint8Array(buffer);
    console.log(uint8); // [137, 80, 78, 71, ...]
  };

  // 方式3:读为文本
  reader.readAsText(file, 'utf-8');
  reader.onload = () => {
    console.log(reader.result); // "文件内容字符串"
  };
});

URL.createObjectURL() vs FileReader(图片预览)

const file = e.target.files[0];

// ✅ 推荐:URL.createObjectURL() - 同步、性能好
const url1 = URL.createObjectURL(file);
img.src = url1;
// 用完记得释放
img.onload = () => URL.revokeObjectURL(url1);

// ⚠️ 传统:FileReader - 异步、较慢
const reader = new FileReader();
reader.readAsDataURL(file);
reader.onload = () => {
  img.src = reader.result; // "data:image/png;base64,..."
};
对比项 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];
  // 方案1:推荐(性能好)
  const url = URL.createObjectURL(file);
  preview.src = url;
  preview.onload = () => URL.revokeObjectURL(url);

  // 方案2:需要Base64时
  // const reader = new FileReader();
  // reader.readAsDataURL(file);
  // reader.onload = () => preview.src = reader.result;
});
</script>

📤 文件上传(FormData + Blob)

const file = e.target.files[0];

// 直接上传File(继承自Blob)
const formData = new FormData();
formData.append('file', file, file.name);
fetch('/upload', {
  method: 'POST',
  body: formData
});

// 或者:截取部分上传(Blob切片)
const chunk = file.slice(0, 1024 * 1024); // 前1MB
formData.append('chunk', chunk);

🎨 Canvas导出图片

const canvas = document.querySelector('canvas');
const ctx = canvas.getContext('2d');

// Canvas → Blob
canvas.toBlob((blob) => {
  // 生成预览URL
  const url = URL.createObjectURL(blob);
  const img = document.createElement('img');
  img.src = url;

  // 或转为Base64上传
  const reader = new FileReader();
  reader.readAsDataURL(blob);
  reader.onload = () => {
    console.log(reader.result); // "data:image/png;base64,..."
  };
}, '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; // undefined
}

// ✅ 正确:用Promise
function read(file) {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.readAsDataURL(file);
  });
}

核心要点总结

💡 关键知识点

← 返回首页