前言
在 JavaScript 中,File 和 Blob 是 Web API 提供的两个重要对象,用于处理文件和二进制数据。它们被广泛应用于文件上传、下载、读取以及数据操作等场景。
blob
Blob 对象表示一个不可变的、原始数据的类文件对象。它提供了对文件内容的抽象,而不关心具体内容本身。你可以使用 Blob 来存储二进制数据。可以用来存储文件、图片、音频、视频、甚至是纯文本等各种类型的数据。Blob 提供了一种高效的方式来操作数据文件,而不需要将数据全部加载到内存中,这在处理大型文件或二进制数据时非常有用。
const blob = new Blob(blobParts, options);
blobParts: 一个数组,包含将被放入 Blob 对象中的数据,可以是字符串、数组缓冲区(ArrayBuffer)、TypedArray、Blob 对象等。
options: 一个可选的对象,可以设置 type(MIME 类型)和 endings(用于表示换行符)。
// 创建一个包含文本的 Blob
const textBlob = new Blob(["Hello, Blob!"], { type: "text/plain" });
console.log(textBlob); // Blob { size: 12, type: "text/plain" }
// 创建一个包含二进制数据的 Blob
const binaryBlob = new Blob([new Uint8Array([72, 101, 108, 108, 111])], { type: "application/octet-stream" });
console.log(binaryBlob); // Blob { size: 5, type: "application/octet-stream" }
Blob 对象主要有以下几个属性:
size: 返回 Blob 对象的大小(以字节为单位)。
console.log(blob.size); // 输出 Blob 的大小
type: 返回 Blob 对象的 MIME 类型。
console.log(blob.type); // 输出 Blob 的 MIME 类型
Blob 对象提供了一些常用的方法来操作二进制数据。
1、slice([start], [end], [contentType])
该方法用于从 Blob 中提取一部分数据,并返回一个新的 Blob 对象。
参数 start 和 end 表示提取的字节范围,contentType 设置提取部分的 MIME 类型。
const blob = new Blob(["Hello, Blob!"], { type: "text/plain" });
const partialBlob = blob.slice(0, 5);
2、text()
该方法将 Blob 的内容读取为文本字符串。它返回一个 Promise,解析为文本数据。
blob.text().then((text) => {
console.log(text); // 输出 "Hello, Blob!"
});
3、arrayBuffer()
该方法将 Blob 的内容读取为 ArrayBuffer 对象,适合处理二进制数据。它返回一个 Promise,解析为 ArrayBuffer 数据。
const blob = new Blob(["Hello, Blob!"], { type: "text/plain" });
blob.arrayBuffer().then((buffer) => {
console.log(buffer);
});
ArrayBuffer 的实际应用:图片预览
const fileInput = document.querySelector('#fileInput');
fileInput.addEventListener('change', (event) => {
const file = event.target.files[0];
file.arrayBuffer().then((arrayBuffer) => {
const blob = new Blob([arrayBuffer], { type: file.type });
const objectURL = URL.createObjectURL(blob);
const img = document.createElement('img');
img.src = objectURL;
document.body.appendChild(img);
URL.revokeObjectURL(objectURL); // 释放资源
});
});
4、stream()
stream() 是 Blob 对象的一个方法,用于将 Blob 的数据作为一个 ReadableStream 返回。这种方式允许以流的方式逐块读取数据,非常适合处理 大文件,避免一次性加载整个文件到内存中,节约资源。
const readableStream = blob.stream();
// 返回值: 一个 ReadableStream,用于逐步读取 Blob 的内容。
// 用途:
// 处理大文件的流式传输。
// 避免大文件占用大量内存。
示例1、使用 ReadableStream 读取数据块
const blob = new Blob(["Hello, World!"], { type: "text/plain" });
const reader = blob.stream().getReader(); // 获取流的 reader
reader.read().then(function process({ done, value }) {
if (done) {
console.log('Stream complete');
return;
}
console.log(new TextDecoder().decode(value)); // 解码并打印每块数据
return reader.read().then(process); // 继续读取下一块数据
});
示例2、流式上传文件
const uploadFile = async (file) => {
const reader = file.stream().getReader();
while (true) {
const { done, value } = await reader.read();
if (done) {
console.log('File upload complete');
break;
}
// 将每块数据上传到服务器
await fetch('/upload', {
method: 'POST',
body: value,
});
}
};
const fileInput = document.querySelector('#fileInput');
fileInput.addEventListener('change', (event) => {
const file = event.target.files[0];
uploadFile(file);
});
Blob 的使用场景
1、生成文件下载
可以通过 Blob 创建文件并生成下载链接供用户下载文件
// 动态生成一个文本文件
const blob = new Blob(["Hello, World!"], { type: "text/plain" });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = "example.txt"; // 文件名
document.body.appendChild(a);
a.click();
URL.revokeObjectURL(url); // 释放 URL 对象
2、上传文件
将用户上传的文件通过 Blob 或 FormData 传输到服务器。
const fileInput = document.querySelector('#fileInput');
fileInput.addEventListener('change', async (event) => {
const file = event.target.files[0];
const formData = new FormData();
formData.append('file', file);
const response = await fetch('/upload', {
method: 'POST',
body: formData,
});
console.log('File uploaded:', response.ok);
});
3、文件预览
用于在网页上显示用户上传的文件内容,比如图片、音频、视频或 PDF 文件。
// 1 文件预览图片
const input = document.querySelector('#fileInput');
input.addEventListener('change', (event) => {
const file = event.target.files[0];
const url = URL.createObjectURL(file);
const img = document.createElement('img');
img.src = url;
document.body.appendChild(img);
URL.revokeObjectURL(url); // 释放 URL
});
// 2 使用 Canvas 生成图片并保存为 Blob
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'blue';
ctx.fillRect(0, 0, 200, 200);
canvas.toBlob((blob) => {
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'canvas-image.png';
a.click();
URL.revokeObjectURL(url);
}, 'image/png');
4、CSV 或 Excel 数据生成
const data = [
["Name", "Age", "City"],
["Alice", "24", "New York"],
["Bob", "30", "San Francisco"],
];
const csvContent = data.map(row => row.join(',')).join('\n');
const blob = new Blob([csvContent], { type: 'text/csv' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = "data.csv";
a.click();
URL.revokeObjectURL(url);
File
File 是 JavaScript 中代表文件的数据结构,是 Blob 的子类,包含文件的元数据(如文件名、文件大小、类型等)。File 对象通常由用户通过 选择文件时创建,也可以使用 JavaScript 构造函数手动创建。
new File(array, name, options);
// 创建一个 File 对象
const file = new File(["Hello, File!"], "example.txt", { type: "text/plain", lastModified: Date.now() });
console.log(file);
// File { name: "example.txt", size: 12, type: "text/plain", lastModified: 1695644303000 }
File 对象继承了 Blob 对象的方法,因此可以使用一些 Blob 对象的方法来处理文件数据。
1、slice(): 从文件中获取一个子部分数据,返回一个新的 Blob 对象。
const blob = file.slice(0, 1024); // 获取文件的前 1024 个字节
const file = new File(["Hello World!"], "example.txt", { type: "text/plain" });
const blob = file.slice(0, 5); // 获取文件的前 5 个字节
blob.text().then((text) => {
console.log(text); // 输出: "Hello"
});
2、text(): 读取文件内容,并将其作为文本返回(这是 Blob 的方法,但可以用于 File 对象)
const file = new File(["Sample content for file"], "example.txt", { type: "text/plain" });
file.text().then((text) => {
console.log(text); // 输出: "Sample content for file"
});
3、arrayBuffer(): 将文件内容读取为 ArrayBuffer(用于处理二进制数据)。
const file = new File([new Uint8Array([65, 66, 67])], "example.bin");
file.arrayBuffer().then((buffer) => {
const view = new Uint8Array(buffer);
console.log(view); // 输出: Uint8Array(3) [65, 66, 67]
});
4、stream(): 返回一个 ReadableStream 对象,可以通过流式读取文件内容。
const stream = file.stream();
const file = new File(["Chunk 1\nChunk 2\nChunk 3"], "example.txt");
const reader = file.stream().getReader();
reader.read().then(function process({ done, value }) {
if (done) {
console.log("Stream complete");
return;
}
console.log(new TextDecoder().decode(value)); // 输出文件的部分内容
return reader.read().then(process);
});
总结
Blob 是一个通用的二进制数据容器,适合处理动态内容、文件片段等,但不具有文件的元数据(如文件名、最后修改时间等)。
File 是一个包含文件元信息的 Blob,主要用于用户上传文件的场景(File 对象看作是带有文件信息的 Blob)
二者在文件上传和二进制数据处理的场景中被广泛使用。Blob 更加通用,而 File 更专注于与文件系统的交互。