Blob URL vs Data URL
两种在浏览器中引用文件数据的方式,形态相似,机制完全不同。本文解释它们的区别,帮你判断该用哪个。
它们是什么
Data URL
data:image/png;base64,iVBORw0KGgo…文件的完整数据被 Base64 编码后直接写在 URL 里。URL 本身就是数据,可以复制、粘贴、存入数据库或写进 HTML/CSS。
Blob URL
blob:https://example.com/550e8400-e29b…浏览器为内存中的 Blob 或 File 对象生成的临时引用。URL 本身不含数据,只是一个指针,只在当前页面有效。
对比一览
| 项目 | Data URL | Blob URL |
|---|---|---|
| 形态 | data:image/png;base64,iVBOR... | blob:https://example.com/abc-123 |
| 是否包含数据 | 是,数据直接编码在 URL 里 | 否,是指向浏览器内存的引用 |
| 可否复制分享 | 可以,URL 本身就是数据 | 不可以,仅当前页面有效 |
| 内存占用 | 高,Base64 字符串 ≈ 原文件 1.33× | 低,只存一个内部引用 |
| 大文件支持 | 差,体积膨胀 + 浏览器卡顿 | 好,适合任意大小 |
| 生命周期 | 永久(只要字符串存在) | 页面关闭或 revokeObjectURL() 后失效 |
| 写入 HTML / CSS | 可以,直接内嵌 | 不可以,页面刷新后失效 |
| 需要手动释放 | 否 | 是,应调用 revokeObjectURL() |
各自适合的场景
用 Data URL 的场景
- 小图片内嵌到 HTML / CSS(< 5 KB)
- HTML 邮件嵌入图片(不支持 Blob URL)
- @font-face 内联小字体
- JSON API 传递小附件
- 需要复制、存储或传输的文件数据
- SVG favicon 内联到 <link>
用 Blob URL 的场景
- 浏览器端预览上传的图片 / 视频
- 触发文件下载(<a download>)
- Canvas 导出图片后预览
- 大文件处理结果的临时展示
- MediaSource API 流式播放
- 处理 Blob 数据时的临时 URL
代码示例
input.addEventListener('change', (e) => {
const file = e.target.files[0]
const url = URL.createObjectURL(file)
// Preview image
img.src = url
// Trigger download
const a = document.createElement('a')
a.href = url
a.download = file.name
a.click()
// Release when done
URL.revokeObjectURL(url)
})const reader = new FileReader()
reader.onload = (e) => {
const dataUrl = e.target.result
// Embed in HTML, CSS, JSON, or store
img.src = dataUrl
// dataUrl: "data:image/png;base64,iVBOR..."
}
reader.readAsDataURL(file)记得释放 Blob URL
每次调用 URL.createObjectURL() 都会在浏览器内部创建一个对 Blob 数据的引用。即使 JavaScript 中的变量已经被回收,这个引用仍然存在,数据不会被垃圾回收。
应该在合适的时机调用 URL.revokeObjectURL(url) 释放引用:
| 场景 | 合适的释放时机 |
|---|---|
| 触发下载 | 点击后立即 revoke(<a> 的 click 事件后) |
| 图片预览 | 用户选择新文件时,或预览组件卸载时 |
| 视频预览 | 视频播放结束或组件卸载时 |
| React 组件 | useEffect 的 cleanup 函数中 |
相关工具
常见问题
Blob URL 和 Data URL 有什么核心区别?
Data URL 把文件数据编码进 URL 本身(Base64 字符串),可以复制、传输、持久存储。Blob URL 是浏览器内存中 Blob 数据的临时引用,URL 本身不含数据,只在当前页面有效,关闭页面后失效。
预览图片用哪个更好?
Blob URL 更好。URL.createObjectURL() 不复制数据,内存占用接近原文件大小;而 FileReader.readAsDataURL() 会生成一个约原文件 1.33 倍大小的 Base64 字符串。文件越大,差距越明显。
为什么 HTML 邮件只能用 Data URL?
邮件客户端渲染 HTML 时不在浏览器上下文中,无法解析 Blob URL(blob: 协议是浏览器私有的)。Data URL 将图片数据直接内嵌在 HTML 里,邮件客户端可以独立解析,因此是邮件内嵌图片的唯一选择。
不调用 revokeObjectURL 会怎样?
浏览器会一直持有对 Blob 数据的内部引用,即使 JavaScript 变量已被回收,数据也无法被垃圾回收。如果页面频繁创建 Blob URL 而不释放,内存会持续增长,直到页面关闭才会释放。
Blob URL 能存到数据库或 localStorage 吗?
不能,存了也没用。Blob URL 只在创建它的页面生命周期内有效,刷新页面后即使 URL 字符串还在,指向的数据也已经消失。需要持久化的数据应使用 Data URL 或先上传到服务器。
如何把 Blob URL 转为 Data URL?
用 fetch 请求 Blob URL 拿到 Blob 数据,再用 FileReader.readAsDataURL() 转换:fetch(blobUrl).then(r => r.blob()).then(blob => { const reader = new FileReader(); reader.onload = e => console.log(e.target.result); reader.readAsDataURL(blob) })