前端文件( Blob、File、FileReader、ArrayBuffer、Object URL……)

2,393 阅读3分钟

我们在业务开发中经常涉及到和二进制文件相关的操作,有些概念我们可能听过、用过,但是没有真正去了解过,例如 Blob、File、FileReader、ArrayBuffer等等。下面就会通过一个实际的例子演示一下这些文件类型和转换的操作。

File对象

File对象出自input类型为file,文件上传之后返回的FileList对象。

<input type="file" id="fileId" />
function getFile() {
  var file = document.getElementById('fileId')
  return file.files[0]
}
var fileObj = getFile() // 这个是file对象
fileObj instanceof File
fileObj instanceof Blob // File是继承自Blob的

Blob对象

如上面的例子,File是继承自Blob的。Blob(Binary Large Object)表示一个不可变、原始数据的类文件对象。

接上面的例子,我们可以用Blob构造函数,将File对象转成Blob对象

let blobObj = new Blob([fileObj], {
  type: fileObj.type
})

Blob对象有一些属性和方法:

  • size 文件大小
  • type 文件的类型
  • slice: ƒ slice() 传入开始下标和结束下标(不包括这个位置),以及内容属性,创建出新的Blob,一般用于文件分片上传
  • arrayBuffer: ƒ arrayBuffer(),按ArrayBuffer的方式读取文件,返回一个Promise
  • text: ƒ text(),按文本的方式读取文件,返回一个Promise
  • stream: ƒ stream() 读取文件流,返回一个ReadableStream对象
blobObj.arrayBuffer().then(res => console.log(res))
blobObj.text().then(res => console.log(res))
blobObj.stream()
blobObj.slice(0, 1).text().then(res => console.log(res))

Blob对象转内存链接

有些业务场景下,我们需要把Blob对象转成链接,进行内容预览或者下载,此时就需要URL.createObjectURL方法了。

let url1 = URL.createObjectURL(fileObj) // 也可以用于File对象
let url2 = URL.createObjectURL(blobObj)
console.log(url1, url2)

得到的链接如果浏览器认识,就可以直接用这个链接预览;如果不认识,也可以将其下载下来。下面的方法就是文件下载的通用方法,传入的res将其转成Blob,再转成URL进行下载。

const createLink = (res, name, type) => {
  let blob = null;
  if (type) {
    blob = new Blob([res], type);
  } else {
    blob = new Blob([res]);
  }
  let link = document.createElement('a');
  link.download = name;
  link.href = URL.createObjectURL(blob);
  link.click();
};

使用FileReader将blob转成其他类型的数据

let fileRead = new FileReader()
fileRead.readAsText(blobObj) // 文本
fileRead.readAsDataURL(blobObj) // base64
fileRead.readAsArrayBuffer(blobObj) // ArrayBuffer
fileRead.abort() // 中断读取操作

其中readAsTextreadAsArrayBuffer,效果和Blob自带的text()arrayBuffer()是一样的。另外,FileReader还提供了对读取过程的监听的回调,以及中断读取的方法。

截屏2024-08-08 23.34.01.png

Blob转成Response对象

const response = new Response(blobObj)

// 这些方法都会返回一个Promise
response.arrayBuffer().then(res => console.log(res))
response.blob().then(res => console.log(res))
response.json().then(res => console.log(res))
response.text().then(res => console.log(res))

ArrayBuffer是什么

上面多次提到了ArrayBuffer,我们来看看ArrayBuffer是什么。

ArrayBuffer表示存储二进制数据的一段内存,通过TypedArrayDataView进行读写。

TypedArray操作:

名称占有空间(字节)备注
Int8Array18位有符号整数
Uint8Array18位无符号整数
Uint8ClampedArray18位无符号整型固定数值(0-255)
Int16Array216位有符号整数
Uint16Array216位无符号整数
Int32Array432位有符号整数
Uint32Array432位无符号整数
Float32Array432位浮点数
Float64Array864位浮点数

DataView操作:

let dataView = new DataView(bufferObj)
// 定义了一些读写的方法

截屏2024-08-08 23.44.56.png

常见场景:通讯系统对二进制数据的处理,发送数据和解析数据都会用到,例如protobuf

一般前后端会约定一个消息的格式,例如定义前N位是发送人,第N+1到第M为是发送时间,后X位是消息内容等等。然后从后端推送过来的消息要按照这个格式解析,发送给服务器的消息要按照这个格式组装。

Demo

github.com/beat-the-bu…