ITPub博客

首页 > 应用开发 > Java > 别再滥用 Base64 了——Blob 才是前端减负的正确姿势

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

Java 作者:oliseh 时间:2025-12-17 10:53:54 0 删除 编辑

一、什么是 Blob?

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

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


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


const blob = 
new 
Blob(parts, options);
参数 说明
parts 数组,元素可以是 String、 ArrayBuffer、 TypedArray、 Blob 等。
options 可选对象,常用字段:
type MIME 类型,默认 application/octet-stream;
endings 是否转换换行符,几乎不用。

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


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. 生成方式


const url = 
URL.
createObjectURL(blob);

// 返回值样例

// blob:https://localhost:3000/550e8400-e29b-41d4-a716-446655440000

2. 生命周期

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

最佳实践封装:


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. 本地图片/视频预览(零上传)


<
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 并下载

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)


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 头 。

<""><""><""><"">

<"www.hat.olbzhibo.com"><""><""><"www.kite.olbzhibo.com">


六、踩坑指南与性能锦囊

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

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

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


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

<""><""><"www.nest.olbzhibo.com"><"">

<""><"www.rat.olbzhibo.com"><""><"www.top.olbzhibo.com">

<""><""><""><"www.knot.olbzhibo.com">

<""><""><""><"">

<"www.pant.olbzhibo.com"><"www.quit.olbzhibo.com"><""><"">

<"www.tent.olbzhibo.com"><"www.tree.olbzhibo.com"><"www.uxxt.olbzhibo.com"><"">

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/53956/viewspace-3105440/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
不仅仅专注Oracle database技术, member of SHOUG

注册时间:2014-04-06

  • 博文量
    300
  • 访问量
    1959755