在日常开发中,我们经常会遇到需要处理图片数据的场景。比如从服务器返回的是一串 Base64 编码的图片,或者某些离线缓存的数据以 Base64 形式存储,如何将这段看似乱码的字符串变为一个可以插入页面 <img>
标签显示的资源?
本篇文章围绕一个具体实战场景展开:如何将 Base64 编码转换为 Blob 对象,再生成临时 URL,并将图片插入到页面中
📌 为什么需要从 Base64 转为 Blob?
Base64 是一种将二进制数据用可打印字符表示的方式,优点是通用、跨平台、传输方便。但它也有明显的弊端:
- 占用空间大:Base64 编码的字符串体积比原始二进制数据大约多了 33%;
- 浏览器直接处理效率低:对于需要展示、下载、上传的资源,更推荐用
Blob
对象来封装; - 与现代 API 不兼容:如 FormData、File、fetch 上传等都更适配 Blob/File 类型。
因此,将 Base64 转换为 Blob 是一种更标准、更高效的做法,特别是在需要将资源进一步操作或传输时。
🧩 原始代码 & 步骤解析
先来看一段完整的代码示例,并逐行解释它做了什么。
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>base64ToBlob</title>
</head>
<body>
<script>
// 第一步:使用 atob 解码 base64 字符串 → 原始二进制字符串(每个字符表示一个字节)
const base64Data = atob('iVBORw0KGgoAAAANSUhEUgAAARMAAAC3CAMAAAAGjUrGAAABgFBMVEX...');
// 第二步:创建 Uint8Array,长度与二进制字符串相同,用于存放每个字节(0-255)
const byteArray = new Uint8Array(base64Data.length);
// 第三步:遍历 base64 解码后的字符串,将每个字符的 Unicode 编码作为对应字节存入数组
for (let i = 0; i < base64Data.length; i++) {
byteArray[i] = base64Data.charCodeAt(i);
}
// 第四步:构造 Blob 对象,将字节数组作为其内容,并指定 MIME 类型为 image/png
const blob = new Blob([byteArray], { type: 'image/png' });
// 第五步:使用 URL.createObjectURL 生成一个临时可访问的本地 URL
const url = URL.createObjectURL(blob);
// 第六步:创建 <img> 元素,将其 src 设置为上述 URL,实现图片展示
const img = document.createElement('img');
img.src = url;
document.body.appendChild(img);
</script>
</body>
</html>
🔍 每一步都做了什么?
1. Base64 解码:atob()
ini
const base64Data = atob(base64String);
atob
的作用是将 Base64 编码字符串解码为原始二进制字符串;- 得到的不是可读文字,而是一个"每个字符等于一个字节"的原始字符串;
- 注意,这不是数组,也不是 Buffer,而是纯字符串表示的字节序列。
2. 构造字节数组:Uint8Array
ini
const byteArray = new Uint8Array(base64Data.length);
- JavaScript 的
Uint8Array
是一个定长的无符号 8 位整数数组; - 用于存放字节数据,每项值为 0~255,正好适合处理图片这种原始二进制内容;
- 它比字符串更高效,也符合 Blob 的数据结构要求。
3. 将字符转为字节值
css
for (let i = 0; i < base64Data.length; i++) {
byteArray[i] = base64Data.charCodeAt(i);
}
- 这是将"字符串格式的字节"转换为真正数值型的字节;
charCodeAt()
获取当前字符对应的 Unicode 编码(对于atob
的返回值,每个字符的编码正好就是其字节值);- 得到的
byteArray
才是真正可以打包成 Blob 的数据结构。
4. Blob 对象的创建
go
const blob = new Blob([byteArray], { type: 'image/png' });
Blob
是 HTML5 引入的构造器,用于封装任意类型的二进制数据;type
指定 MIME 类型,这样浏览器就知道这是个 PNG 图片;- 可将多个
ArrayBuffer
、字符串、TypedArray
封装成一个 Blob。
5. Blob → URL:创建可访问链接
ini
const url = URL.createObjectURL(blob);
URL.createObjectURL
会返回一个临时的本地 URL(形如blob:http://xxx/xxxxxx
);- 这个 URL 可以像普通图片地址一样设置在
img.src
中; - 它不依赖服务器、不占用资源,仅在当前页面有效。
6. 图片插入页面展示
ini
const img = document.createElement('img');
img.src = url;
document.body.appendChild(img);
- 这样,我们就用纯前端方式,把一个 base64 编码的图片,动态转换成了可展示的图片资源;
- 这个过程没有上传,没有下载,所有操作都在浏览器端完成,效率极高。
🧠 延伸:Blob 的实际应用场景
除了本文中的用法,Blob 还被广泛应用于以下场景:
✅ 文件下载
ini
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'example.png';
a.click();
可以用 Blob 构建一个临时链接,模拟文件下载,让用户一键保存数据。
✅ 上传二进制文件
php
const formData = new FormData();
formData.append('file', blob, 'upload.png');
fetch('/upload', {
method: 'POST',
body: formData
});
将 Blob 当作文件上传,尤其适合画板截图、canvas 导出、音频录制等场景。
✅ 音频/视频播放
ini
const video = document.createElement('video');
video.src = URL.createObjectURL(mediaBlob);
video.controls = true;
document.body.appendChild(video);
Blob 可以用于存储和播放录制的音视频数据,常用于直播、会议系统中。
Blob 有什么优势(为什么不直接用 Base64)?
这是一个容易忽略但很关键的问题。我们可以简单对比一下 Base64 和 Blob 各自的特点:
特性 | Base64 | Blob |
---|---|---|
表示方式 | 字符串 | 二进制对象(类似文件) |
空间效率 | 占用原始大小的约 1.37 倍 | 原始大小 |
创建方式 | 将字节转为字符串 | 将字节数组或字符串直接封装 |
浏览器处理效率 | 慢,尤其是大文件 | 快,天然支持流式和异步操作 |
适合用途 | 小图标、内嵌样式 | 下载、上传、文件处理、Media流处理 |
✅ Blob 的优势总结如下:
- 节省内存和带宽:Base64 会把数据变大(大约 33%),Blob 保持原始大小。
- 更快的处理速度:Blob 不需要将数据再转为字符串解析,性能上更好。
- 可流式处理 :Blob 可用于
fetch
、FormData
、Stream
等接口,更贴近真实的文件传输。 - 可用于 DOM 直接操作 :像
createObjectURL
可以生成 URL,直接用于<img>
、<a>
、<video>
等标签中,简化操作流程。