概念介绍
Blob
Blob( Binary large object)表示二进制类型的大对象。在数据库管理系统中,将二进制数据存储为一个单一个体的集合。
在 JavaScript
中, Blob
对象表示一个不可变、原始数据的类文件对象。
为了更直观的感受 Blob 对象,我们先来使用 Blob 构造函数,创建一个 Blob 实例,具体如下图所示:
该 Blob 实例含有两个属性:size 和 type。其中 size
属性用于表示数据的大小(以字节为单位),type
是 MIME 类型的字符串。
File
文件(File
)接口提供有关文件的信息,并允许网页中的 JavaScript 访问其内容。
通常情况下, File
对象是来自用户在一个 <input type="file" />
元素上选择文件后返回的 FileList
对象,也可以是来自由拖放操作生成的 DataTransfer
对象。
File
对象是特殊类型的 Blob
,File
接口基于Blob
,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
Base64
Base64 是一组相似的二进制到文本(binary-to-text)的编码规则,使得二进制数据在解释成 radix-64 的表现形式后能够用 ASCII 字符串的格式表示出来。
在 JavaScript 中,有两个函数被分别用来处理解码和编码 base64 字符串:
atob()
函数能够解码通过base-64编码的字符串数据。相反地,btoa()
函数能够从二进制数据“字符串”创建一个base-64编码的ASCII字符串。
atob()
和 btoa()
均使用字符串。
每一个Base64字符实际上代表着6比特位。因此,3字节(一字节是8比特,3字节也就是24比特)的字符串/二进制文件可以转换成4个Base64字符(4x6 = 24比特)。
这意味着Base64格式的字符串或文件的尺寸约是原始尺寸的133%(增加了大约33%)。如果编码的数据很少,增加的比例可能会更高。
Data URLs
Data URLs,即前缀为 data:
协议的URL,其允许内容创建者向文档中嵌入小文件。
Data URLs 由四个部分组成:前缀(data:
)、指示数据类型的MIME类型、如果非文本则为可选的base64
标记、数据本身:
data:[<mediatype>][;base64],<data>
mediatype 是个 MIME 类型的字符串,例如 image/jpeg
表示 JPEG 图像文件。如果被省略,则默认值为 text/plain;charset=US-ASCII
如果数据是文本类型,你可以直接将文本嵌入 (根据文档类型,使用合适的实体字符或转义字符)。如果是二进制数据,你可以将数据进行base64编码之后再进行嵌入。
下面是一些示例:
-
data:,Hello%2C%20World!
简单的 text/plain 类型数据
-
data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D
上一条示例的 base64 编码版本
Data URL 可以直接插入 html 某些标签的 src 属性,进行预览。比如 img 和 audio 等。 Blob 和 File 对象则可以通过 URL.createObjectURL(),创建一个临时链接,实现预览。
ArrayBuffer、TypedArray、DataView
ArrayBuffer
对象、TypedArray
视图和DataView
视图是 JavaScript 操作二进制数据的一个接口。
二进制数组由三类对象组成。
(1)ArrayBuffer
对象:代表内存之中的一段二进制数据,可以通过“视图”进行操作。“视图”部署了数组接口,这意味着,可以用数组的方法操作内存。
(2)TypedArray
视图:共包括 9 种类型的视图,比如Uint8Array
(无符号 8 位整数)数组视图, Int16Array
(16 位整数)数组视图, Float32Array
(32 位浮点数)数组视图等等。
(3)DataView
视图:可以自定义复合格式的视图,比如第一个字节是 Uint8(无符号 8 位整数)、第二、三个字节是 Int16(16 位整数)、第四个字节开始是 Float32(32 位浮点数)等等,此外还可以自定义字节序。
简单说,ArrayBuffer
对象代表原始的二进制数据,TypedArray
视图用来读写简单类型的二进制数据,DataView
视图用来读写复杂类型的二进制数据。
类型之间互转
Base64 与 Blob 互转
Base64 —> Blob
// 小红点base64供使用测试
const contentType = "image/png";
const b64Data =
"iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==";
function b64toBlob(b64Data, contentType = "", sliceSize = 512) {
// 先将base64数据解码为字符串
const byteCharacters = atob(b64Data);
const byteArrays = [];
// byteCharacters 可能很大,为了性能,可以按 512 拆分处理,最后再合起来。
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
// 创建一个数组,填充每个位字符的 Unicode 码点
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
// 生成Uint8Array
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, { type: contentType });
return blob;
}
以上这种方式其实是通过字符串的 charCodeAt
方法来生成 Uint8Array
的。
实际上还有一种简便的方法,就是利用 Data URLs 和 fetch。
利用浏览器的 fetch
api,向 DataURL 发起请求,再利用返回的 Response 对象进行转化。代码如下:
async function b64toBlob(b64Data, contentType = "") {
const url = `data:${contentType};base64,${b64Data}`;
const res = await fetch(url);
return res.blob(); // 同理也可以 res.arrayBuffer() 返回 ArrayBuffer
}
Blob —> Base64
Blob
转 Base64
可以利用浏览器提供的 FileReader
对象。FileReader
对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File
或 Blob
对象指定要读取的文件或数据。
function blobToDataURL(blob) {
return new Promise(resolve => {
const reader = new FileReader();
reader.onload = function (e) {
resolve(e.target.result);
};
reader.readAsDataURL(blob); // 这里是DataURL 如果需要纯base64的话需要自己取
});
}
ArrayBuffer 与 Blob 互转
ArrayBuffer —> Blob
这个转换比较简单,Blob
构造函数支持直接传染一个 ArrayBuffer
const ab = new ArrayBuffer(32);
const blob = new Blob([ab]); // 注意必须包裹[]
Blob —> ArrayBuffer
使用 Blob.arrayBuffer()
,可以返回一个promise且包含blob所有内容的二进制格式的 ArrayBuffer。
代码用法如下。
const blob = new Blob(['hello world'], { type: 'text/plain'});
blob.arrayBuffer().then(buffer => /* 处理 ArrayBuffer 数据的代码……*/);
其实还有另外一个方法,利用浏览器提供的 FileReader
对象,来看看代码。
function blobToArrayBuffer(blob) {
return new Promise(resolve => {
const reader = new FileReader();
reader.onload = function (e) {
resolve(e.target.result);
};
reader.readAsArrayBuffer(blob);
});
}
ArrayBuffer 与 Base64 互转
base64 —> ArrayBuffer
其实这里与 base64
转 Blob
的方式有点像,不同的地方是直接用 Unit8Array
转换成 ArrayBuffer
。
function base64ToArrayBuffer(base64) {
const binaryString = atob(base64);
const len = binaryString.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}
另外一种方法使用 fetch
的上面已经提供,不再赘述。
ArrayBuffer —> base64
利用 String.fromCharCode 方法,将码点转换成字符串,再利用 btoa()
。
function arrayBufferToBase64(buffer) {
const str = String.fromCharCode(...new Uint8Array(arrayBuffer));
return btoa(str);
}