别再滥用 Base64 了——Blob 才是前端减负的正确姿势

一、什么是 Blob?

Blob (Binary Large Object,二进制大对象)是浏览器提供的一种不可变、类文件的原始数据容器 。它可以存储任意类型的二进制或文本数据,例如图片、音频、PDF、甚至一段纯文本。与 File 对象相比,Blob 更底层,File 实际上继承自 Blob,并额外携带了 namelastModified 等元信息 。

Blob 最大的特点是纯客户端、零网络:数据一旦进入 Blob,就活在内存里,无需上传服务器即可预览、下载或进一步加工。


二、构造一个 Blob:一行代码搞定

js 复制代码
const blob = new Blob(parts, options);
参数 说明
parts 数组,元素可以是 StringArrayBufferTypedArrayBlob 等。
options 可选对象,常用字段: type MIME 类型,默认 application/octet-streamendings 是否转换换行符,几乎不用。

示例:动态生成一个 Markdown 文件并让用户下载

js 复制代码
const content = '# Hello Blob\n> 由浏览器动态生成';
const blob = new Blob([content], { type: 'text/markdown' });
const url = URL.createObjectURL(blob);

const a = document.createElement('a');
a.href = url;
a.download = 'hello.md';
a.click();

// 内存用完即弃
URL.revokeObjectURL(url);

三、Blob URL:给内存中的数据一个"临时地址"

1. 生成方式

js 复制代码
const url = URL.createObjectURL(blob);
// 返回值样例
// blob:https://localhost:3000/550e8400-e29b-41d4-a716-446655440000

2. 生命周期

  • 作用域 :仅在当前文档、当前会话 有效;页面刷新、close()、手动调用 revokeObjectURL() 都会使其失效 。
  • 性能陷阱 :不主动释放会造成内存泄漏,尤其在单页应用或大量图片预览场景 。

最佳实践封装:

js 复制代码
function createTempURL(blob) {
  const url = URL.createObjectURL(blob);
  // 自动 revoke,避免忘记
  requestIdleCallback(() => URL.revokeObjectURL(url));
  return url;
}

四、Blob vs. Base64 vs. ArrayBuffer:如何选型?

场景 推荐格式 理由
图片回显、<img>/<video> Blob URL 浏览器可直接解析,无需解码;内存占用低。
小图标内嵌在 CSS/JSON Base64 减少一次 HTTP 请求,但体积增大约 33%。
纯计算、WebAssembly 传递 ArrayBuffer 可写、可索引,适合高效运算。
上传大文件、断点续传 Blob.slice 流式分片,配合 File.prototype.slice 做断点续传 。

五、高频实战场景

1. 本地图片/视频预览(零上传)

html 复制代码
<input type="file" accept="image/*" id="uploader">
<img id="preview" style="max-width: 100%">

<script>
uploader.onchange = e => {
  const file = e.target.files[0];
  if (!file) return;
  const url = URL.createObjectURL(file);
  preview.src = url;
  preview.onload = () => URL.revokeObjectURL(url); // 加载完即释放
};
</script>

2. 将 Canvas 绘图导出为 PNG 并下载

js 复制代码
canvas.toBlob(blob => {
  const url = URL.createObjectURL(blob);
  const a = document.createElement('a');
  a.href = url;
  a.download = 'snapshot.png';
  a.click();
  URL.revokeObjectURL(url);
}, 'image/png');

3. 抓取远程图片→Blob→本地预览(跨域需 CORS)

js 复制代码
fetch('https://i.imgur.com/xxx.png', { mode: 'cors' })
  .then(r => r.blob())
  .then(blob => {
    const url = URL.createObjectURL(blob);
    document.querySelector('img').src = url;
  });

若出现图片不显示 ,99% 是因为服务端未返回 Access-Control-Allow-Origin 头 。


六、踩坑指南与性能锦囊

坑点 解决方案
内存暴涨 每次 createObjectURL 后,务必在合适的时机 revokeObjectURL
跨域失败 确认服务端开启 CORS;fetch 时加 {credentials: 'include'} 如需 Cookie。
移动端大视频卡顿 避免一次性读完整文件,使用 blob.slice(start, end) 分段读取。
旧浏览器兼容 IE10+ 才原生支持 Blob;如需更低版本,请引入 Blob.js 兼容库。

七、延伸:Blob 与 Stream 的梦幻联动

当文件超大(GB 级)时,全部读进内存并不现实。可以借助 ReadableStream 把 Blob 转为流,实现渐进式上传:

js 复制代码
const stream = blob.stream(); // 返回 ReadableStream
await fetch('/upload', {
  method: 'POST',
  body: stream,
  headers: { 'Content-Type': blob.type }
});

Chrome 85+、Edge 85+、Firefox 已经支持 blob.stream(),能以流式形式边读边传,内存占用极低。


八、总结:记住"三句话"

  1. Blob = 浏览器端的二进制数据仓库,File 只是它的超集。
  2. Blob URL = 指向内存的临时指针,用完后必须手动或自动释放。
  3. 凡是"本地预览、零上传、动态生成下载"的需求,优先考虑 Blob + Blob URL 组合。

用好 Blob,既能提升用户体验 (秒开预览),又能降低服务端压力(无需中转),是每一位前端工程师的必备技能。

相关推荐
QQ1__8115175151 小时前
Spring boot名城小区物业管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
前端·vue.js·spring boot
钛态2 小时前
前端微前端架构:大项目的救命稻草还是自找麻烦?
前端·vue·react·web
一粒黑子2 小时前
【实战解析】阿里开源 PageAgent:纯前端 GUI Agent,一行JS让网页支持自然语言操控
前端·javascript·开源
独角鲸网络安全实验室2 小时前
2026微信小程序抓包全解析:从实操落地到合规风控,解锁前端调试新范式
前端·微信小程序·小程序·抓包·系统代理绕过·https证书严格校验·进程隔离
紫微AI2 小时前
前端文本测量成了卡死一切创新的最后瓶颈,pretext实现突破了
前端·人工智能·typescript
GISer_Jing2 小时前
AI前端(From豆包)
前端·aigc·ai编程
IT枫斗者2 小时前
前端部署后如何判断“页面是不是最新”?一套可落地的版本检测方案(适配 Vite/Vue/React/任意 SPA)
前端·javascript·vue.js·react.js·架构·bug
测试修炼手册2 小时前
[测试技术] 深入理解 JSON Web Token (JWT)
前端·json
AI老李2 小时前
2026 年 Web 前端开发的 8 个趋势!
前端
里欧跑得慢2 小时前
15. Web可访问性最佳实践:让每个用户都能平等访问
前端·css·flutter·web