了解下源码中提到的 Blob、ArrayBuffer、FileReader、ObjectURL、Base64 的解码与编码。
ArrayBuffer
缓冲区又称为缓存,它是内存空间的一部分,也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据
缓冲区是内存空间的一部分,它等待着数据的存取,那为什么不直接进行数据的存取还费那么大劲申请一块缓冲区再存取数据,因为缓冲区相当于一种媒介,介于输入和输出之间
ArrayBuffer 是一种数据类型
- 用于表示通用的、固定长度的原始二进制数据缓冲区
- 相关属性与方法
- byteLength 表示数组的字节大小,在数据创建时确定,并且不可变更,只读
- slice:返回一个新的 ArrayBuffer ,它的内容是这个 ArrayBuffer 的字节副本
- 不能直接操作 ArrayBuffer 的内容,需要通过类型数组对象或 DataView 对象来操作,它们会将缓冲区的数据表示为特定的格式,并通过这些格式来读写缓冲区的内容
- 类型数组对象
- DataView
类型化数组就是一种类似数组的对象,它提供了一种用于访问原始二进制数据的机制
- Float32Array Float64Array
- Int8Array Int16Array Int32Array
- Uint8Array Uint16Array Uint32Array
- BigInt64Array BigUint64Array
FileReader
具体两个从现有数据中获取 ArrayBuffer 的例子
通过 FileReader 从用户系统读取文件内容,通过 File 或 Blob 对象指定要读取的文件或数据
- 通过 file input 或 drop 事件的 dataTransfer 属性读取文件
- 相关读取 api
- readAsArrayBuffer:一旦完成,result 属性中保存的是将被读取文件的 ArrayBuffer 数据对象
- readAsDataURL:一旦完成,result 属性中将包含一个
data:
URL 格式的 Base64 字符串以表示所读取文件的内容 - readAsText:一旦完成,result 属性中将包含一个字符串以表示所读取的文件内容
ObjectURL
使用对象的 URL:在某个时候,引入了对 DOM window.URL.createObjectURL() 和 window.URL.revokeObjectURL() 方法的支持,使得你可以创建引用任何数据的简单 URL 字符串。
// HTML 中通过 URL 来引用 File 对象时。你可以像使用普通 URL 那样使用它,比如用在 img.src 上。
var objectURL = window.URL.createObjectURL(fileObj);
// 每个创建了的对象URL必须要释放。当文档关闭时,它们会自动被释放。
window.URL.revokeObjectURL(objectURL);
Blob
Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制格式进行读取,也可以转换成 ReadableStream 用于数据操作。
File 接口基于 Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。
关键方法
- slice([start[, end[, contentType]]]):返回一个新的 Blob 对象,包含了源 Blob 对象中指定范围内的数据
- stream():返回一个能读取 blob 内容的 ReadableStream
- text():返回一个 promise 且包含 blob 所有内容的 UTF-8 格式的 USVString
- arrayBuffer():返回一个 promise 且包含 blob 所有内容的二进制格式的 ArrayBuffer
Base64
Base64 是一组相似的二进制到文本的编码规则,使得二进制数据在解释成 radix-64 的表现形式后,能够用 ASCII 字符串的格式表示出来。
有两个函数被分别用来处理解码和编码 base64 字符串:
- atob():解码通过 base-64 编码的字符串数据
- btoa():从二进制数据“字符串”创建一个 base-64 编码的 ASCII 字符串
编码尺寸增加:每一个 Base64 字符实际上代表着 6 比特位。因此,3 字节(一字节是 8 比特,3 字节也就是 24 比特)的字符串/二进制文件可以转换成 4 个 Base64 字符(4x6 = 24比特)。这意味着 Base64 格式的字符串或文件的尺寸约是原始尺寸的 133%(增加了大约 33%)。如果编码的数据很少,增加的比例可能会更高。
TextEncoder、TextDecoder 类
TextEncoder:接收 USVString 作为输入,encode 方法,接受一个 USVString 作为输入,返回一个包含文本的 Uint8Array,其中的文本使用 UTF-8 编码。
TextDecoder:文本解码器,将字节流作为输入,USVString 作为输出
AbortController
AbortController 类
- 实验中的特性,可以配合 Fetch API 实现请求的取消
- 构造函数创建一个 controller 实例,然后通过 signal 属性获取它的关联对象 AbortSignal 的引用
- 将 signal 传入 Fetch API 中,通过调用 controller.abort() 实现对于请求的取消
ReadableStream
Fetch API 中 Response.body 返回一个暴露其 body 内容的 ReadableStream 流
ReadableStream 类
- cancel() 取消读取流,可传入 reason 参数表示取消原因
- getReader() 创建一个读取器并将流锁定于其上、一旦流被锁定,其他读取器将不能读取它,知道它被释放
- tee() 返回包含两个 ReadableStream 实例分支的数组,每个元素接收了相同的传输数据
通过 Stream 的方式计算进度
export function streamProgress(stream, onprogress) {
const reader = stream.getReader();
let current = 0;
reader.read().then(calc).catch(console.error)
function calc(ev) {
if (!ev.done) {
reader.read().then(calc).catch(console.error)
}
ev.value && (current += ev.value.length)
onprogress(current)
}
return stream
}
export function downloadProgress(response, onprogress) {
const total = response.headers.get("Content-Length")
const tee = response.body.tee()
streamProgress(tee[0], bytesCount => onprogress && onprogress(bytesCount / total))
return new Response(tee[1])
}
扩展
XMLHttpRequest 对象,传送数据的时候,有一个 progress 事件,用来返回进度信息。
它分成上传和下载两种情况
- 下载的progress事件属于 XMLHttpRequest 对象
- 上传的progress事件属于 XMLHttpRequest.upload 对象