js Blob 与 ArrayBuffer

一、Blob

概念:

Blob(Binary Large Object)表示二进制类型的大对象,通常是影像、音频、文本等多媒体文件;在 javascript 中,Blob 类型的对象是不可改变的原始数据

语法:

new Blob(blobParts, option)

示例:

  1. 通过字符串创建一个 Blob
    1 const helloWorld = new Blob(["hello", " world"], {
    2     type: "text/plain",
    3     endings: "transparent",
    4 });
    5 console.log(helloWorld); // Blob {size: 11, type: 'text/plain'}
  2. 通过 Blob 创建一个新的 Blob
    1 const helloVue = new Blob([helloWorld.slice(0, 5), " vue"], {
    2     type: "text/plain",
    3     endings: "transparent",
    4 });
    5 console.log(helloVue); // Blob {size: 9, type: 'text/plain'}
  3. 分片上传
     1 function handle(blob, chunkSize, upload) {
     2     const size = blob.size;
     3     let start = 0,
     4         end = chunkSize;
     5     while (start < size) {
     6         upload(blob.slice(start, end, "text/plain"));
     7         start = end;
     8         end = start + chunkSize;
     9     }
    10 }
    11 // 每次上传 4 个字节哈哈
    12 handle(helloVue, 4, (chunk) => console.log(chunk));

二、Blob URL

概念:

Blob URL 是一种伪协议,浏览器内部为每个 Blob URL 存储了一个 URL → Blob 的映射,如果这个映射不存在了,则会从浏览器中收到 404 错误;因此,此类 URL 较短,生成的 URL 仅在当前文档下才有效

特性:

由于有映射关系的存在,Blob 无法释放;可以手动销毁映射,或关闭当前文档

示例:

 1 const link = URL.createObjectURL(helloVue);
 2 const _link = URL.createObjectURL(helloVue);
 3 console.log(link); // blob:null/fffb6ef0-9a06-4503-b982-058929da566b
 4 console.log(_link); // blob:null/cdbb625f-c99a-4d4e-bd10-70136f0d270a /* Blob URL 是随机的 */
 5 
 6 /* 可以作为 a 标签的 link;如果是图片,也可以作为 img 的 src */
 7 
 8 // 销毁 Blob URL;否则 Blob 得不到释放,会产生内存泄漏
 9 URL.revokeObjectURL(link);
10 URL.revokeObjectURL(_link);

三、File

概念:

继承自 Blob

语法:

new File(blobParts, name, option)

示例:

1 // 创造一个 .txt 文件
2 const file = new File([helloVue], "test.txt", {
3     type: "text/plain",
4 });

四、FileReader

作用:

用来读取 Blob,并转换为其他类型的数据

转换方式:

readAsArrayBuffer、readAsBinaryString、readAsDataURL、readAsText

示例:

1 const reader = new FileReader();
2 
3 reader.onload = function (e) {
4     console.log(this.result); // hello vue
5 };
6 reader.readAsText(file);

五、ArrayBuffer

概念:

表示通用的、固定长度的原始二进制缓冲区

与数组的区别:

数组存在在堆中,ArrayBuffer 存放在栈中

与 Blob 的区别:

Blob 不可被修改,只能重新创建新的 Blob;ArrayBuffer 可以视图化,然后修改

TypeArray 类型具体包含以下方法:

Int8Array、Uint8Array、Uint8ClampedArray(颜色专用)、Int16Array、Uint16Array、Int32Array、Uint32Array、Float32Array、Float64Array

DataView 类包含以下方法:

getInt8、setInt8、getUint8、setUint8 等;没有与 Uint8ClampedArray 相关对应的方法

示例:

  1. 创建一个长度为 4 个字节的 ArrayBuffer
    1 const buffer = new ArrayBuffer(4);
    2 console.log(buffer); // ArrayBuffer(4)
  2. 创建一个 Int8 视图
    1 const view0 = new Int8Array(buffer);
    2 console.log(view0); // Int8Array(4) [0, 0, 0, 0]
  3. 填充为“food”字符串
    1 "food".split("").forEach(function (char, index) {
    2     view0[index] = char.charCodeAt(0);
    3 });
    4 console.log(view0); // Int8Array(4) [102, 111, 111, 100]
  4. 转为字符串
    1 const food = String.fromCharCode.apply(null, view0);
    2 console.log(food); // food
  5. 转为数组
    1 const foodUnicode = Array.from(view0);
    2 console.log(foodUnicode); // [102, 111, 111, 100]
  6. 也可以直接创建一个已填充的视图
    1 const view1 = new Int8Array(foodUnicode);
    2 console.log(view1); // Int8Array(3) [102, 111, 111, 100]
  7. 复制一段缓冲区
    1 // 类型化数组的 set 方法用于复制一段内存;它是整段内存的复制,比一个个拷贝成员的那种复制快得多
    2 const view2 = new Int8Array(8);
    3 view2.set(view0);
    4 console.log(view2); // Int8Array(8) [102, 111, 111, 100, 0, 0, 0, 0]
  8. 也可以截取一段缓冲区
    1 const fooBuffer = view1.buffer.slice(0, 3);
    2 const fooView = new Int8Array(fooBuffer);
    3 console.log(fooView); // Int8Array(3) [102, 111, 111]
  9. 转为 Blob
    1 const foo = new Blob([fooBuffer], {
    2     type: "text/plain",
    3     endings: "transparent",
    4 });
    5 console.log(foo); // Blob {size: 3, type: 'text/plain'}

六、Data URL

格式:

data:[MIME type];encoding,content

七、实战

通过文件二进制头判断文件类型

 1 <input type="file" onchange="handle(event)" />;
 2 <script>
 3     function getFileType(file) {
 4         return new Promise((resolve, reject) => {
 5             if (!file) return;
 6             const types = ["PNG", "GIF"];
 7             let fileType = "";
 8             file.arrayBuffer().then((buffer) => {
 9                 const view = new Uint8Array(buffer.slice(0, 8));
10                 const fileHead = String.fromCharCode.apply(null, view);
11                 types.forEach(function (type) {
12                     if (fileHead.includes(type)) {
13                         fileType = type;
14                     }
15                 });
16                 resolve(fileType);
17             });
18         });
19     }
20     function handle(e) {
21         const file = e.target.files[0];
22         getFileType(file).then((res) => {
23             console.log(res);
24         });
25     }
26 </script>
posted @ 2022-11-18 21:20  万物有序  阅读(1095)  评论(0编辑  收藏  举报