我们在业务开发中经常涉及到和二进制文件相关的操作,有些概念我们可能听过、用过,但是没有真正去了解过,例如 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() // 中断读取操作
其中readAsText和readAsArrayBuffer,效果和Blob自带的text()和arrayBuffer()是一样的。另外,FileReader还提供了对读取过程的监听的回调,以及中断读取的方法。
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表示存储二进制数据的一段内存,通过TypedArray和DataView进行读写。
TypedArray操作:
| 名称 | 占有空间(字节) | 备注 |
|---|---|---|
| Int8Array | 1 | 8位有符号整数 |
| Uint8Array | 1 | 8位无符号整数 |
| Uint8ClampedArray | 1 | 8位无符号整型固定数值(0-255) |
| Int16Array | 2 | 16位有符号整数 |
| Uint16Array | 2 | 16位无符号整数 |
| Int32Array | 4 | 32位有符号整数 |
| Uint32Array | 4 | 32位无符号整数 |
| Float32Array | 4 | 32位浮点数 |
| Float64Array | 8 | 64位浮点数 |
DataView操作:
let dataView = new DataView(bufferObj)
// 定义了一些读写的方法
常见场景:通讯系统对二进制数据的处理,发送数据和解析数据都会用到,例如protobuf。
一般前后端会约定一个消息的格式,例如定义前N位是发送人,第N+1到第M为是发送时间,后X位是消息内容等等。然后从后端推送过来的消息要按照这个格式解析,发送给服务器的消息要按照这个格式组装。