ArrayBuffer、Blob/File和TypeArray之间的关系

33 阅读2分钟

ArrayBuffer用来表示通用的原始二进制数据缓冲区,简单来说,就是js提供的操作内存中二进制数据的一个接口,最初是为了满足js和显卡之间大量的、实时的数据交换,它们之间的数据通讯必须是二进制的,而不能使用传统的文本,因此有了ArrayBuffer这样的接口。但是这是一个只读的对象,我们不能直接操作ArrayBuffer,为此,专门提供了类型化数组对像TypeArray来操作ArrayBuffer。在js中没有TypeArray这样的构造函数,而是有许多具体的类型化数组,比如:Int8Array Uint8Array Uint8ClampedArray Int16Array Uint16Array Int32Array Uint32Array Float32Array Float64Array BigInt64Array BigUint64Array。类型化数组可以根据ArrayBuffer来生成,类型化数组上也有一个属性buffer来获取它所对应的ArrayBuffer。

接下来就该说一下File和Blob对象,这两个是前端用来操作文件的对象,File是从Blob继承而来的。File和Blob都可以基于ArrayBuffer来创建,因为文件从本质上来说,也是一些内存二进制数据。File可以通过FileReader来读取,Blob可以通过createObjectURL生成一个内存地址,然后将这个地址赋值给a标签的href属性来下载。

另外再明确两个接口的含义,分别是atob和btoa。这两个接口和前端的base64编码规则有关,这个base64编码规则并不是图片等其他文件的base64格式的字符串(可以使用FileReader获取到),而是一组相似的二进制到文本的编码规则,因此如果是文件的base64字符串使用atob是会报错的,atob和btoa的使用可以参考以下代码:

// 用法
const uint8Arr = new TextEncoder().encode("a Ā 𐀀 文 🦄");
const binString = Array.from(uint8Arr, (byte) =>{
  return String.fromCodePoint(byte)
}).join("");
const baseStr = btoa(binString);// YSDEgCDwkICAIOaWhyDwn6aE
const binString1 = atob(baseStr);
const uint8Arr1 = Uint8Array.from(binString1, (m) => m.codePointAt(0));
new TextDecoder().decode(uint8Arr1); // "a Ā 𐀀 文 🦄"