提示:记录工作中遇到的需求及解决办法
文章目录
前言
在前端开发的旅途中,我们总会与 Blob、File、FileReader、ArrayBuffer、Base64、URL.createObjectURL() 这些“老朋友”不期而遇。通常,我们会祭出“万能”搜索引擎,复制粘贴一段代码,完成任务后便拍拍手走人,从未深究这些概念背后的奥秘。是时候痛下决心,抽出十分钟,一起搞懂这些“神秘代码”的真相!让我们在开发的江湖中,不再只是“复制侠”,而是“代码大师”!
Blob
Blob 对象表示一个不可变、原始数据的 「类文件」 对象。它的数据可以按文本 (text()方法) 或二进制(arrayBuffer()方法)的格式进行读取,也可以转换成 ReadableStream (stream()方法)可读流来用于数据操作。Blob 提供了一种高效的方式来操作数据文件,而不需要将数据全部加载到内存中(比如流式读取、文件切片 slice() 方法),这在处理大型文件或二进制数据时非常有用。
Blob 表示的不一定是 JavaScript 原生格式的数据,它还可以用来存储文件、图片、音频、视频、甚至是纯文本等各种类型的数据。
File 接口基于 Blob,继承了 blob 的功能并将其扩展以支持用户系统上的文件。
基本使用
可以使用 new Blob() 构造函数来创建一个 Blob 对象:
new Blob(blobParts)
new Blob(blobParts, options)
- blobParts (可选):一个可迭代对象,比如 Array,包含 ArrayBuffer、TypedArray、DataView、Blob、字符串或者任意这些元素的混合,这些元素将会被放入 Blob 中。
- options (可选):可以设置 type (MIME 类型)和 endings (用于表示换行符)。
const blob1 = new Blob(["Hello, world!"], {
type: "text/plain" });
const blob2 = new Blob(['<q id="a"><span id="b">hey!</span></q>'], {
type: "text/html" });
Blob 对象主要有以下几个属性:
- size: 返回 Blob 对象的大小(以字节为单位)。
console.log(blob.size); // 输出 Blob 的大小
- type: 返回 Blob 对象的 MIME 类型。
console.log(blob.type); // 输出 Blob 的 MIME 类型
Blob 对象提供了一些常用的方法来操作二进制数据。
- slice([start], [end], [contentType])
该方法用于从 Blob 中提取一部分数据,并返回一个 「新的 Blob 对象」。参数 start 和 end 表示提取的字节范围,contentType 设置提取部分的 MIME 类型。
const blob = new Blob(["Hello, world!"], {
type: "text/plain" });
const partialBlob = blob.slice(0, 5);
- text()
该方法将 Blob 的内容读取为文本字符串。它返回一个 Promise,解析为文本数据。
blob.text().then((text) => {
console.log(text); // 输出 "Hello, world!"
});
- arrayBuffer()
该方法将 Blob 的内容读取为 ArrayBuffer 对象,适合处理二进制数据。它返回一个 Promise,解析为 ArrayBuffer 数据。
const blob = new Blob(["Hello, world!"], {
type: "text/plain" });
blob.arrayBuffer().then((buffer) => {
console.log(buffer);
});
4. stream()
该方法将 Blob 的数据作为一个 ReadableStream 返回,允许你以流的方式处理数据,适合处理大文件。
const blob = new Blob(["Hello, world! This is a test Blob."], {
type: 'text/plain' });
// 获取 Blob 的可读流
const readableStream = blob.stream();
// 创建一个默认的文本解码器
const reader = readableStream.getReader();
// 用于读取流并输出到控制台
function readStream () {
reader.read().then(({
done, value }) => {
if (done) {
console.log('Stream complete'); return; }
// 将 Uint8Array 转换为字符串并输出
console.log(new TextDecoder("utf-8").decode(value));
// 继续读取下一个块
return reader.read().then(processText);
}).catch(err => {
console.error('Stream failed:', err);
});
}
readStream();
一个更复杂的示例:将一个 Blob 的内容流式读取并将其写入到另一个流中(了解即可)
const blob = new Blob(["Hello, world! This is a test Blob."], {
type: 'text/plain' });
// 使用 Blob.stream() 方法获取一个可读流
const readableStream = blob.stream();
// 创建一个新的 Response 对象,以便使用 Response.body 作为可读流
const response = new Response(readableStream);
// 使用 TextDecoderStream 将二进制流转换为字符串
const textDecoderStream = new TextDecoderStream();
readableStream.pipeTo(textDecoderStream.writable);
// 获取解码后的可读流
const decodedStream = textDecoderStream.readable;
// 创建一个可写流目标,通常是显示在页面上或传输到服务器
const writableStream = new WritableStream({
write (chunk) {
console.log(chunk); // 在控制台输出解码后的文本
// 这里你可以将数据写入到某个地方,比如更新网页内容或上传到服务器
}, close () {
console.log('Stream complete');
}
});