JS 二进制之 File、Blob、FileReader、ArrayBuffer、Base64

1. Blob

Blob【Binary large object】即二进制大对象,表示原始文件的数据。它表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转成 ReadableStream 来用于数据操作。简单来说,Blob 就是一个不可修改的二进制文件

1.1 Blob 创建

sql 复制代码
new Blob(array, options);
  • array 是一个包含字符串、ArrayBuffer、ArrayBufferView、Blob 等的数组或可迭代对象。多个 BlobParts 会按照它们在数组中的顺序进行连接以形成 Blob。如果省略该参数,则创建一个空的 Blob。
  • options 是一个对象,可选属性为
    • type 【较常用】 ,默认值为"",表示放入到 blob 对象中内容的 MIME 类型

【补】: 常见的 MIME 类型如下:

MIME 类型 描述
text/plain 纯文本文档
text/html HTML 文档
text/javascript JavaScript 文件
text/css CSS 文件
application/json JSON文件
application/pdf PDF文件
application/xml XML 文件
image/jpeg JPEG图像
image/png PNG图像
image/gif GIF 图像
image/svg+xml SVG 图像
audio/mpeg MP3 文件
video/mpeg MP4 文件

1.2 Blob 切片

Blob 对象内置了 slice() 方法用来将 blob 对象分片,其语法如下:

ini 复制代码
const blob = instanceOfBlob.slice([start [, end [, contentType]]]};

其有三个参数:

  • start:设置切片的起点,即切片开始位置。默认值为 0,这意味着切片应该从第一个字节开始;
  • end:设置切片的结束点,会对该位置之前的数据进行切片。默认值为blob.size
  • contentType:设置新 blob 的 MIME 类型。如果省略 type,则默认为 blob 的原始值。

下面来看例子:

ini 复制代码
const iframe = document.getElementsByTagName("iframe")[0];

const blob = new Blob(["Hello World"], {type: "text/plain"});

const subBlob = blob.slice(0, 5);

iframe.src = URL.createObjectURL(subBlob);

此时页面会显示"Hello"。

2. File

File对象 其实就是特殊类型的 Blob,即 Blob 的属性和方法同样适用于 File 对象。

JS 中主要有两个地方产生 File 对象:

  • 通过<input type='file'> 元素上传文件后,返回的 FileList 对象
  • 文件拖放操作生成的 DataTransfer 对象

2.1 < input / >

ini 复制代码
<input type="file" id="fileInput" multiple="multiple">
const fileInput = document.getElementById("fileInput");
fileInput.onchange = (e) => {
  console.log(e.target.files); 
}

2.2 文件拖放

ini 复制代码
<div id="drop-zone"></div>

const dropZone = document.getElementById("drop-zone"); 
dropZone.ondragover = (e) => { 
   e.preventDefault();
} 
dropZone.ondrop = (e) => { 
  e.preventDefault(); 
  const files = e.dataTransfer.files; 
  console.log(files)
}

注意:

  • 两个拖拽事件中都需要添加 e.preventDefault(),用来阻止默认事件,可以阻止浏览器的一些默认行为。比如默认浏览器不允许任何拖拽操作!!

  • e.dataTransfer.files 的属性值是一个 FileList 数组。

3. FileReader

FileReader 是一个异步 API,用于读取文件并提取其内容以供进一步使用。 【 FileReader 可以将 Blob 读取为不同的格式!!】

3.1 基本使用

3.1.1 创建对象:
ini 复制代码
const reader = new FileReader();
3.1.2 自身方法:
  • readAsArrayBuffer() :读取指定 Blob 中的内容,完成之后,result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象;

  • FileReader.readAsBinaryString() :读取指定 Blob 中的内容,完成之后,result 属性中将包含所读取文件的原始二进制数据

  • FileReader.readAsDataURL() :读取指定 Blob 中的内容,完成之后,result 属性中将包含一个data: URL 格式的 Base64 字符串以表示所读取文件的内容。

  • FileReader.readAsText() :读取指定 Blob 中的内容,完成之后,result 属性中将包含一个字符串以表示所读取的文件内容。

可以看到,上面这些方法都接受一个要读取的 blob 对象作为参数,读取完之后会将读取的结果放入对象的 result 属性中。

3.1.3 事件处理:
  • abort:该事件在读取操作被中断时触发;
  • error:该事件在读取操作发生错误时触发;
  • load:该事件在读取操作完成时触发;
  • progress:该事件在读取 Blob 时触发。

当然,这些方法可以加上前置 on 后在HTML元素上使用,比如onloadonerroronabortonprogress。除此之外,由于 FileReader对象继承自EventTarget ,因此还可以使用 addEventListener() 监听上述事件。

注意: progress 事件提供了两个属性:loaded(已读取量)和total(需读取总量)。

4. ArrayBuffer

ArrayBuffer 对象用来表示通用的、固定长度的原始二进制数据缓冲区。ArrayBuffer 的内容不能直接操作,只能通过 DataView 对象或 TypedArrray 对象来访问。这些对象用于读取和写入缓冲区内容。

注意: ArrayBuffer 本身就是一个黑盒,不能直接读写所存储的数据,需要借助以下视图对象来读写。

ArrayBuffer vs Blob: Blob 作为一个整体文件,适合用于传输当需要对二进制数据进行操作时(比如要修改某一段数据时),就可以使用 ArrayBuffer。

具体操作方法详见 谈谈JS二进制

5. Object URL

Object URL 又称 Blog URL,它是一个用来表示File Object 或Blob Object 的URL。在网页中,我们可能会看到过这种形式的 Blob URL: 创建一个指向 Blob 或 File 对象的可以用作图像、二进制数据下载链接等的 URL 源,可以在 < img /> < script /> 中用当作 src 属性的值!!

arduino 复制代码
const objUrl = URL.createObjectURL(new File([""], "filename")); console.log(objUrl); URL.revokeObjectURL(objUrl);

6. Base64

Base64 是一种基于64个可打印字符来表示二进制数据的表示方法。Base64 编码普遍应用于需要通过被设计为处理文本数据的媒介< img />上储存和传输二进制数据而需要编码该二进制数据的场景。这样是为了保证数据的完整并且不用在传输过程中修改这些数据。

在 JavaScript 中,有两个函数被分别用来处理解码和编码 base64 字符串:

  • atob():解码,解码一个 Base64 字符串;
  • btoa():编码,从一个字符串或者二进制数据编码一个 Base64 字符串。

6.1 应用场景

6.1.1 toDataURL()方法把 canvas 画布内容生成 base64 编码格式的图片
javascript 复制代码
const canvas = document.getElementById('canvas'); const ctx = canvas.getContext("2d"); const dataUrl = canvas.toDataURL();
6.1.2 readAsDataURL()方法把读取的文件转为base64格式的data URL返回

7. 总结如下

相关推荐
慧一居士44 分钟前
flex 布局完整功能介绍和示例演示
前端
DoraBigHead1 小时前
小哆啦解题记——两数失踪事件
前端·算法·面试
一斤代码6 小时前
vue3 下载图片(标签内容可转图)
前端·javascript·vue
中微子6 小时前
React Router 源码深度剖析解决面试中的深层次问题
前端·react.js
光影少年6 小时前
从前端转go开发的学习路线
前端·学习·golang
中微子7 小时前
React Router 面试指南:从基础到实战
前端·react.js·前端框架
3Katrina7 小时前
深入理解 useLayoutEffect:解决 UI "闪烁"问题的利器
前端·javascript·面试
前端_学习之路8 小时前
React--Fiber 架构
前端·react.js·架构
coderlin_8 小时前
BI布局拖拽 (1) 深入react-gird-layout源码
android·javascript·react.js
伍哥的传说8 小时前
React 实现五子棋人机对战小游戏
前端·javascript·react.js·前端框架·node.js·ecmascript·js