前言
大家好,最近我在开发一个 AI 图片生成项目时遇到了一个技术问题:图片服务器返回的是 Base64 格式的图片数据,但前端需要将其转换成ObjectURL才能在页面上高效渲染。今天,我将分享 为什么需要 Base64 转 ObjectURL,以及 如何实现这个转换。
Base64是什么?
Base64 是一种基于 64 个可打印字符(A-Z, a-z, 0-9, +, /)的编码方式,用于将二进制数据(如图片、音频、PDF)转换成 ASCII 字符串,使其可以在文本协议(如 HTTP、JSON)中安全传输。
比如下面这张图片以及它的Base64格式
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAyAAAAJYCAYAAACadoJwAAAgAElEQVR4AezBSZJkCZul5fc7t1FVazwiE6FAEECKmjNiAmtAmLEPVsCACStgDaygFsAKkgmjQgSpQZEIjZRkZf5/NG56v4OpmTdmHuEe4RF+r6qbn+cp3y......
它的特点是:
- 体积比原始二进制数据大约 增加 33% (因为每 3 字节变成 4 字符)。
- 可以直接内嵌在 HTML/CSS/JS 中(如
<img src="data:image/png;base64,...">)。
ObjectURL是什么?
ObjectURL(URL.createObjectURL())是浏览器提供的一种机制,用于将二进制对象转换成临时 URL(注意是临时的URL),该 URL 可以直接用于 <img>、<video>、<a> 等标签。
还是上面这张图,看看它的临时url
blob:http://127.0.0.1:5500/cb2b964a-4851-4223-9881-1cfe228ba53b
为什么需要Base64转URL?
虽然 Base64 可以直接内嵌使用,但在实际项目中,Base64 → ObjectURL 的转换更优,原因如下:
| 场景 | Base64 直接使用 | Base64 → ObjectURL |
|---|---|---|
| 数据体积 | 体积膨胀 33%,增加传输和内存开销 | 原始二进制数据,无额外膨胀 |
| 渲染性能 | 每次访问需重新解码,CPU 消耗高 | 仅解码一次,后续直接引用 URL,性能高 |
| 内存管理 | 无法主动释放,可能内存泄漏 | 可手动 revokeObjectURL() 释放 |
| 适用场景 | 小图标(<1KB)、测试数据 | 大文件(图片、PDF、视频等) |
在我的项目中,有AI 生成图片这个业务,返回的是Base64的编码格式,所以我需要使用转成ObjectURl的方式,有助于前端渲染。
具体实现
1.将Base64编码的格式转换为原始的二进制数据
const base64Data = atob('iVBORw0KGgoAA......') //Base64 => 原始二进制
此时让我们打印base64Data这个对象,看看是否成功
console.log(base64Data)
可以看到,控制台输出的全是乱码
这是正常现象,根本原因是atob() 函数的作用是将 Base64 字符串 解码为原始二进制数据的字符串表示
而当控制台尝试显示这些二进制数据时:
-
对于可打印 ASCII 字符(32-126):正常显示
-
对于不可打印字符(0-31, 127-255):
- 浏览器可能显示为 � 符号
- 或显示为乱码字符
- 或显示为空白
2.转换成Uint8Array
为了解决上面的乱码问题,我们需要将这里的base64Data进行处理:转换成Uint8Array
const byteArray = new Uint8Array(base64Data.length);
for(let i = 0 ; i < base64Data.length ;i++){
byteArray[i] = base64Data.charCodeAt(i);
}
console.log(byteArray)
Uint8Array 是 JavaScript 提供的 无符号 8 位整型数组,专门用于存储 原始二进制数据。它的优势:1.精确表示字节数据,每个元素对应一个字节,不会像上面的字符串那样受编码影响出现乱码,2.它和我们后面要转换的Blob更兼容
我们输出byteArray,此时能够看到byteArray中每一个元素都是的8位无符号整型(0-255),一个字节也就是8位,所以刚好一个元素对应一个字节,完美匹配二进制数据存储需求,所以Uint8Array是JavaScript很常用的处理二进制数据的方式。
3.转换成Blob
上面的过程已经得到了二进制的数据了,接下来我们创建一个JavaScript中表示二进制数据的对象--Blob
const blob = new Blob([byteArray],{type:'image/png'})
将刚刚的Uint8Array 转换为 Blob 是前端处理二进制数据的关键步骤,因为我们最后一步的URL.createObjectURL()只能兼容BLob这种,而不能直接处理Uint8Array,Blob是一个王者对象:
-
Blob允许指定type(如"image/jpeg"),明确数据类型,而Uint8Array仅是原始字节,无类型信息。 -
Blob是File的父类,可轻松转换为文件对象(通过new File([blob], 'filename'))。 -
Blob内部可能使用更高效的二进制存储机制(如内存映射文件),尤其适合大文件(如图片、视频)。
| 操作 | Uint8Array | Blob |
|---|---|---|
| 生成 ObjectURL | ❌ 不支持 | ✅ 支持 |
| 指定文件类型 | ❌ 无 | ✅ 可设 |
| 分片读取(.slice()) | 需手动实现 | ✅ 原生支持 |
| 兼容 Fetch/FileReader | ❌ 需转换 | ✅ 直接支持 |
Blob 是浏览器生态中二进制数据的标准交互格式,而 Uint8Array 仅是底层字节容器。转换后才能真正利用 Web API 功能。
4.URL.createObjectURL()
最后就是将二进制数据转换成可访问的url了,我们使用URL.createObjectURL(),并使用DOM编程将URL给放在对应的元素上!
const imageUrl = URL.createObjectURL(blob);
console.log(imageUrl) //blob:http://127.0.0.1:5500/38252332-a4cd-4fc3-8b22-10727db0d4a6
document.getElementById("blobImage").src = imageUrl;
URL.createObjectURL() 是浏览器提供的 API,它用于为 Blob 或 File 对象生成一个临时本地 URL(格式如 blob:http://example.com/xxx)。需要注意的是:生成的 URL 仅在当前文档生命周期内有效,页面刷新或关闭后自动失效。
现在我们就能看到了以下页面效果:
总结一下整个过程
完整代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<img src="" alt="" id="blobImage" width="800" height="800">
<script>
const base64Data = atob('iVBORw0KGgoAAAANSUhEUgAAAyAAAAJYCAYAAACadoJwAAAgAElEQVR4AezBSZJkCZul5fc7t1FVazwiE6FAEECKmjNiAmtAmLEPVsCACStgDaygFsAKkgmjQgSpQZEIjZRkZf5/NG56v4OpmTdm...')
const byteArray = new Uint8Array(base64Data.length);
for(let i = 0 ; i < base64Data.length ;i++){
byteArray[i] = base64Data.charCodeAt(i);
}
const blob = new Blob([byteArray],{type:'image/png'})
const imageUrl = URL.createObjectURL(blob);
document.getElementById("blobImage").src = imageUrl;
</script>
</body>
</html>
让我们总结一下整个过程的流程吧:
-
转换原始Base64:将原始的Base64编码的格式转换成二进制数据,利用
atob()得到base64Data -
转换成无符号 8 位整型数组:创建一个新对象
Uint8Array存储原始的二进制数据base64Data,得到兼容性更强的byteArray,完美匹配二进制的存储要求 -
得到“王者对象”Blob:将
byteArray转换成更高效的二进制实例对象Blob,有助于更好地操作和管理二进制数据 -
得到临时url:用
URL.createObjectURL()为Blob生成一个临时的本地URL,并使用DOM编程将URL给放在对应的元素上,就可以在页面上看到效果了!
总结
在Web开发中,处理二进制数据(特别是图片)时,Base64转ObjectURL是优化性能与内存管理的关键技术。Base64虽然便于文本传输,但其体积膨胀33%且无法主动释放内存,直接内嵌会导致重复解码和资源浪费。通过转换为ObjectURL,我们实现了三大优势:
- 性能提升:二进制数据仅解码一次,生成的Blob URL可重复使用;
- 内存可控:通过
revokeObjectURL()主动释放资源; - 兼容性:完美适配
<img>、fetch等浏览器API。
想必在看完后,你应该也能了解这种处理Base64格式的方式了吧!它是我们前端项目开发中,特别对于图片业务开发十分重要的一种方式!此方案特别适合AI生成图片、大文件预览等场景,是前端处理二进制数据的行业标准实践。