醋醋百科网

Good Luck To You!

前端需要知道的二进制流_js 二进制流

通过本文您将了前端二进制流,base64,Protobuf(Protocol Buffers)等相关知识

前端开发中,二进制流(Binary Stream)是以二进制形式传输或处理的原始数据序列,核心用于处理非文本类数据(如图片、文件、音视频),是实现文件上传 / 下载、Canvas 导出、音视频处理等功能的基础。

一、前端核心二进制相关对象

前端操作二进制流依赖浏览器提供的 API,核心对象如下:

对象名

核心作用

关键场景

Blob

二进制数据的 “容器”,可指定 MIME 类型(如 image/png)

1. 二进制数据转成可下载的文件
2. 生成 URL 供 <img>/<video> 直接加载

ArrayBuffer

内存中连续的二进制数据缓冲区(纯数据,无格式)

1. 读写二进制数据的 “底层载体”
2. 处理二进制协议(如自定义通信格式)

TypedArray

基于 ArrayBuffer 的 “视图”,提供格式化读写(如 Int8、Uint32)

1. 操作具体二进制数值(如处理像素、解析文件头)
2. 数据类型转换(如将 4 字节转成 32 位整数)

DataView

更灵活的 ArrayBuffer 视图,支持任意字节偏移和数据类型读写

解析非对齐的二进制数据(如自定义文件格式、网络协议)

二、前端操作二进制流的核心场景

1. 文件上传:读取本地文件二进制流

通过 <input type="file"> 获取文件,再用 FileReader 读取其二进制数据(File 本质是特殊的 Blob)。

const input = document.querySelector('input[type="file"]');
input.onchange = (e) => {
  const file = e.target.files[0]; // File 对象(继承 Blob)
  const reader = new FileReader();
  
  // 方式1:读成 ArrayBuffer(适合处理二进制数据)
  reader.readAsArrayBuffer(file);
  reader.onload = () => {
    const buffer = reader.result; // ArrayBuffer 实例
    const uint8Arr = new Uint8Array(buffer); // 用 TypedArray 解析
    console.log('文件前10字节:', uint8Arr.subarray(0, 10));
  };

  // 方式2:读成 Blob URL(适合预览,如 <img> 显示)
  const blobUrl = URL.createObjectURL(file);
  document.querySelector('img').src = blobUrl;
};

2. 文件下载:将二进制流转成可下载文件

后端返回二进制流(响应头 Content-Type: application/octet-stream)时,前端用 Blob 包装并生成下载链接。

fetch('/api/download-file')
  .then(res => res.blob()) // 将响应转成 Blob
  .then(blob => {
    // 生成临时 URL
    const url = URL.createObjectURL(blob);
    // 创建 <a> 标签触发下载
    const a = document.createElement('a');
    a.href = url;
    a.download = 'filename.pdf'; // 下载文件名
    a.click();
    // 释放 URL 避免内存泄漏
    URL.revokeObjectURL(url);
  });

3. Canvas 导出:将画布转成二进制图片

通过 canvas.toBlob() 直接生成图片格式的 Blob,再用于下载或上传。

const canvas = document.querySelector('canvas');
// 导出为 PNG 格式的 Blob
canvas.toBlob(
  (blob) => {
    // 场景1:上传到后端(FormData 携带 Blob)
    const formData = new FormData();
    formData.append('image', blob, 'canvas.png');
    fetch('/api/upload', { method: 'POST', body: formData });

    // 场景2:下载图片
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = 'canvas.png';
    a.click();
  },
  'image/png', // MIME 类型
  0.9 // 质量(仅 JPG 有效)
);

三、关键注意点

  1. Blob vs ArrayBuffer:Blob 是 “带格式的二进制容器”(如知道是 image/jpeg),适合直接用于下载、预览;ArrayBuffer 是 “无格式的内存缓冲区”,适合底层数据读写(如解析文件二进制结构)。
  2. 内存泄漏风险
    用 URL.createObjectURL(blob) 生成的 URL 会占用内存,
    必须在使用后用 URL.revokeObjectURL(url) 释放
  3. FormData 上传 Blob
    上传文件时,可直接将 Blob 或 File 放入 FormData,浏览器会自动处理二进制编码(无需手动转 base64)。
  4. 跨域与 Blob URL
    Blob URL 是浏览器本地生成的(格式如 blob:http://xxx),仅当前页面可用,不存在跨域问题,但无法共享给其他页面。

掌握以上内容,即可覆盖前端 90% 以上的二进制流处理场景(文件、图片、简单协议解析)。

四、base64和二进制流什么关系

Base64 和二进制流是同一数据的不同表现形式,二者可以相互转换,核心关系是:
Base64 是二进制流的 “文本编码格式”,用于将二进制数据转换成可打印的 ASCII 文本,方便在只能传输文本的场景中传递二进制信息。

具体关系解析:

  1. 本质区别二进制流:原始的二进制数据(0 和 1 组成的序列),是计算机存储和传输数据的原始形式(如图片、文件的底层数据)。Base64:一种编码算法,将二进制流按照固定规则转换为由 64 个可打印字符(A-Z、a-z、0-9、+、/)组成的字符串。
  2. 例如:二进制流 01001101 01100001(对应字符 "Ma"),经 Base64 编码后会变成字符串 "TWE="。
  3. 转换关系二进制流 → Base64:通过编码算法(每 3 字节二进制数据 → 4 字节 Base64 字符),解决二进制数据在文本协议中传输的问题(如早期邮件协议只支持文本)。Base64 → 二进制流:通过解码算法还原为原始二进制数据,供计算机直接处理(如图片显示、文件保存)。
  4. 使用场景差异二进制流:适合计算机直接处理(如文件存储、网络传输底层数据),体积更小(相同数据比 Base64 小约 25%)。Base64:适合在文本协议中传递二进制数据(如 HTML 中嵌入图片 <img src="data:image/png;base64,...">、JSON 中携带文件数据),但会增加数据体积(约 33%)。

转换示例(JavaScript):

// 1. 二进制流(Blob)转 Base64
const blobToBase64 = (blob) => {
  return new Promise((resolve) => {
    const reader = new FileReader();
    reader.readAsDataURL(blob); // 读取为 DataURL(包含 Base64)
    reader.onload = () => {
      const base64Str = reader.result.split(',')[1]; // 提取纯 Base64 部分
      resolve(base64Str);
    };
  });
};

// 2. Base64 转二进制流(Blob)
const base64ToBlob = (base64Str, mimeType = 'application/octet-stream') => {
  const byteChars = atob(base64Str); // 解码 Base64 为二进制字符串
  const byteArrays = [];
  for (let i = 0; i < byteChars.length; i++) {
    byteArrays.push(byteChars.charCodeAt(i));
  }
  return new Blob([new Uint8Array(byteArrays)], { type: mimeType });
};

总结:Base64 是二进制流的 “文本化表示”,是为了解决二进制数据在文本环境中传输的兼容性问题而设计的编码方式,二者本质上是同一数据的不同形态。

五、Protobuf(Protocol Buffers)

Protobuf(Protocol Buffers)是一种二进制序列化格式,常用于数据传输,但其本质是 “数据序列化协议” 而非 “传输协议”,不过它通常与二进制流传输结合使用。

关键特点解析:

  1. 二进制序列化
    Protobuf 会将结构化数据(如对象、消息)序列化为紧凑的二进制流(而非 JSON 那样的文本格式),因此序列化后的数据体积小、传输效率高(比 JSON 节省 30%-50% 空间)。
  2. 例如,一个包含 name: "Alice" 和 age: 25 的对象,经 Protobuf 序列化后是一串二进制字节(如 0x0A 0x05 41 6C 69 63 65 10 19),而 JSON 则是 {"name":"Alice","age":25} 这样的文本。
  3. 与传输协议的关系
    Protobuf 本身不负责数据传输,仅处理 “数据如何编码为二进制”。实际传输时,序列化后的二进制流通常通过 TCP、HTTP/2 等传输协议发送。
  4. 例如:
  5. gRPC 框架默认使用 Protobuf 作为数据序列化格式,通过 HTTP/2 传输其生成的二进制流。
  6. 自定义 TCP 协议中,可将 Protobuf 二进制流作为消息体发送。
  7. 优势场景
    适合对传输效率要求高的场景(如微服务通信、物联网设备数据交互),因为二进制流比文本格式(JSON/XML)解析更快、传输更省带宽。

总结:

Protobuf 不是传输协议,而是生成二进制流的序列化协议,其核心价值是将数据高效编码为二进制流,以便通过各种传输协议(如 TCP、HTTP)进行传输。可以说,它是 “为二进制流传输设计的序列化方案”。

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言