20250710-前端高手才知道的秘密:Blob_居然这么强大!

原文摘要

🔍 一、什么是 Blob?

Blob(Binary Large Object)是 HTML5 提供的一个用于表示不可变的、原始二进制数据块的对象。

✨ 特点:

  • 不可变性:一旦创建,内容不能修改。
  • 可封装任意类型的数据:字符串、ArrayBuffer、TypedArray 等。
  • 支持 MIME 类型描述,方便浏览器识别用途。

💡 示例:

const blob = new Blob(['Hello World'], { type: 'text/plain' });

🧠 二、Base64 编码的前世今生

虽然名字听起来像是某种“64进制”,但实际上它是一种编码方式,不是数学意义上的“进制”。

📜 起源背景:

Base64 最早起源于电子邮件协议 MIME(Multipurpose Internet Mail Extensions),因为早期的电子邮件系统只能传输 ASCII 文本,不能直接传输二进制数据(如附件)。于是人们发明了 Base64 编码方法,把二进制数据转换成文本形式,从而安全地在网络上传输。

🧩 使用场景:

场景说明
图片嵌入到 HTML/CSS 中Data URI 方式减少请求
JSON 数据中传输二进制信息如头像、加密数据等
WebSocket 发送二进制消息避免使用 ArrayBuffer
二维码生成将图像转为 Base64 存储

⚠️ 注意:Base64 并非压缩算法,它会将数据体积增加约 33%。


🔁 三、从 Base64 到 Blob 的全过程

1. Base64 字符串解码:atob()

JavaScript 提供了一个内置函数 atob(),可以将 Base64 字符串解码为原始的二进制字符串(ASCII 表示)。

const base64Data = 'SGVsbG8gd29ybGQh'; // "Hello world!"
const binaryString = atob(base64Data);

⚠️ 返回的是 ASCII 字符串,不是真正的字节数组。


2. 构建 Uint8Array(字节序列)

为了构造 Blob,我们需要一个真正的字节数组。我们可以用 charCodeAt() 将每个字符转为对应的 ASCII 数值(即 0~255 的整数)。

const byteArray = new Uint8Array(binaryString.length);

for (let i = 0; i < binaryString.length; i++) {
    byteArray[i] = binaryString.charCodeAt(i);
}

现在,byteArray 是一个代表原始图片二进制数据的数组。


3. 创建 Blob 对象

有了字节数组,就可以创建 Blob 对象了:

const blob = new Blob([byteArray], { type: 'image/png' });

这个 Blob 对象就代表了一张 PNG 图片的二进制内容。


4. 使用 URL.createObjectURL() 显示图片

为了让浏览器能够加载这个 Blob 对象,我们需要生成一个临时的 URL 地址:

const imageUrl = URL.createObjectURL(blob);
document.getElementById('blobImage').src = imageUrl;

这样,你就可以在网页中看到这张图片啦!


🛠️ 四、Blob 的核心功能与应用场景

功能说明
分片上传.slice(start, end) 方法可用于大文件切片上传
本地预览Canvas.toBlob() 导出图像,配合 URL.createObjectURL 预览
文件下载使用 a 标签 + createObjectURL 实现无刷新下载
缓存资源Service Worker 中缓存 Blob 数据提升性能
处理用户上传结合 FileReader 和 File API 操作用户文件

🧪 五、Blob 的高级玩法

1. 文件切片上传(分片上传)

const chunkSize = 1024 * 1024; // 1MB
const firstChunk = blob.slice(0, chunkSize);

2. Blob 转换为其他格式

  • FileReader.readAsText(blob) → 文本
  • FileReader.readAsDataURL(blob) → Base64
  • FileReader.readAsArrayBuffer(blob) → Array Buffer

3. Blob 下载为文件

const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'example.png';
a.click();

🧩 六、相关知识点汇总

技术点作用
Base64将二进制数据编码为文本,便于传输
atob()解码 Base64 字符串,还原为二进制字符串
charCodeAt()获取字符的 ASCII 值(0~255)
Uint8Array构建字节数组,表示原始二进制数据
Blob封装二进制数据,作为文件对象使用
URL.createObjectURL()生成临时地址,让浏览器加载 Blob 数据

🧾 七、完整代码回顾

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <title>Blob 实战</title>
</head>
<body>
  <img src="" id="blobImage" width="100" height="100" alt="Blob Image" />

  <script>
    const base64Data = 'UklGRiAHAABXRUJQVlA4IBQHAACwHACdASpQAFAAPok0lEelIyIhMziOYKARCWwAuzNaQpfW+apU37ZufB5rAHqW2z3mF/aX9o/ev9LP+j9KrqSOfp9mf+6WmE1P1yFc3gTlw8B8d/TebelHaI3mplPrZ+Aa0l5qDGv5N8Tt9vYhz3IH37wqm2al+FdcFQhDnObv2+WfpwIZ+K6eBPxKL2RP6hiC/K1ZynnvVYth9y+ozyf88Obh4TRYcv3nkkr43girwwJ54Gd0iKBPZFnZS+gd1vKqlfnPT5wAwzxJiSk+pkbtcOVP+QFb2uDqUhuhNiHJ8xPt6VfGBfUbTsUzYuKgAP4L9wrkT8KU4sqIHwM+ZeKDBpGq58k0aDirXeGc1Odhvfx+cpQaeas97zVTr2pOk5bZkI1lkF9jnc0j2+Ojm/H+uPmIhS7/BlxuYfgnUCMKVZJGf+iPM44vA0EwvXye0YkUUK...';

    const binaryString = atob(base64Data); // Base64 解码
    const byteArray = new Uint8Array(binaryString.length); // 创建 Uint8Array

    for (let i = 0; i < binaryString.length; i++) {
        byteArray[i] = binaryString.charCodeAt(i); // 填充字节数据
    }

    const blob = new Blob([byteArray], { type: 'image/png' }); // 创建 Blob
    const imageUrl = URL.createObjectURL(blob); // 生成 URL

    document.getElementById('blobImage').src = imageUrl; // 显示图片
  </script>
</body>
</html>

📚 八、扩展阅读建议


🧩 九、结语

Blob 是连接 JavaScript 世界与真实二进制世界的桥梁,是每一个想要突破瓶颈的前端开发者必须掌握的核心技能之一。 掌握了 Blob,你就拥有了操作二进制数据的能力,这在现代 Web 开发中是非常关键的一环。 下次当你看到一张图片在网页中加载出来,或者一个文件被顺利下载时,不妨想想:这一切的背后,都有 Blob 的身影。

原文链接

进一步信息揣测

  • Blob不可变性的实际影响:虽然文档强调Blob不可变,但实践中可通过slice()方法组合新Blob来模拟修改效果,这是绕过限制的常用技巧
  • Base64体积膨胀的隐藏成本:Base64增加33%体积的说法是理论值,实际业务中若包含大量冗余数据(如未压缩图片),体积可能膨胀50%以上,严重影响性能
  • atob()的编码陷阱atob()处理非ASCII字符(如中文)会直接报错,需先对原始数据做URIComponent编码,这是新手常踩的坑
  • Blob URL内存泄漏风险createObjectURL()生成的URL必须手动调用revokeObjectURL()释放,否则会持续占用内存,这在SPA应用中容易积累成严重问题
  • 分片上传的行业黑科技:大厂实际分片上传时会先用MD5计算文件指纹,服务器通过指纹实现秒传(已有相同文件则直接返回地址),这个优化方案极少在公开文档提及
  • MIME类型的潜规则:浏览器对某些MIME类型(如application/octet-stream)会强制下载而非预览,而text/csv可能直接展示,这取决于浏览器厂商的私有逻辑
  • Blob与Service Worker的隐秘联动:Blob可被Service Worker缓存并离线使用,但需要额外配置Response对象的headers,这个高级用法在PWA开发中很关键
  • TypedArray的性能玄机:用Uint8Array处理Base64时,直接预分配内存(new Uint8Array(length))比动态push快3-5倍,这在处理大文件时差异显著
  • Safari的私有限制:iOS Safari对Blob URL有特殊限制(如不能用于Web Audio API),需转成ArrayBuffer使用,这是跨平台开发时的隐藏坑点
  • 企业级Blob存储策略:阿里云/OSS等厂商实际存储Blob时会将小文件(<1MB)合并存储,大文件分片存储,这种优化方案能降低30%+存储成本