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元素上使用,比如onload、onerror、onabort、onprogress。除此之外,由于 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. 总结如下

相关推荐
一水鉴天33 分钟前
统一对象拓扑(UOT)设计全链定稿:从三件事分离到三继承 之1 20261010(豆包“查看聊天内容”继续)
前端·css
杨杰39836 分钟前
我给嵌入式设备写了个 6MB 的 JavaScript 运行时(xuan)
javascript
栖凤44 分钟前
Java 的 try-catch 在 Agent 里失效了,我用了 5 个模式才兜住
java·前端·python
粥里有勺糖44 分钟前
视野修炼第136期 | 前端小恐龙"Deno"被收购
前端·github·ai编程
修炼的dance1 小时前
页面塞了13.88 MB字体,导出的PDF只有71 KB
前端
qq_369173631 小时前
如何将 AI 生成的 HTML 网页发布成在线链接?不用自己搭建服务器
前端·人工智能·html·效率工具·html 发布
风花一世月1 小时前
⚡ 我把一座含氢能源园区搬进了浏览器(五类能流实时算守恒,在线直接玩)
前端·人工智能
羲云1 小时前
Claude 越界事件之后:Agent 权限设计为什么不能只靠提示词
前端
行者全栈架构师2 小时前
【鸿蒙心迹】鸿蒙网络请求架构实战——@ohos.net.http 到 Axios 封装、拦截器与统一错误处理(HarmonyOS 7.x)
前端·算法·架构
全栈Agent 小李2 小时前
【无标题】
前端·后端·agent·ai编程·全栈·cursor·mcp