背景
本文主要总结HTML5中,关于Blob对象的相关知识。 Blob:Binary Large Object。
为什么要有Blob对象?
在文件和二进制数据的操作中, 讲JavaScript无法直接处理二进制数据, 而ECMAScript 5引入了Blob对象,允许直接操作二进制数据。
什么是Blob对象?
Blob对象,是一个代表着二进制数据的基本对象。
创建Blob对象:
- Blob构造函数;
- Blob对象的slice方法,将二进制数据按照字节分块,返回一个新的Blob对象。
Blob对象,有两个只读属性:
- size:二进制数据的大小,单位为字节。
- type:二进制数据的MIME类型,全部为小写,如果类型未知,则该值为空字符串。
Blob 构造函数
Blob 构造函数接收两个参数:数据数组和配置对象。
// 从字符串创建
var textBlob = new Blob(['Hello, World!'], { type: 'text/plain' });
console.log(textBlob.size); // 13
console.log(textBlob.type); // "text/plain"
// 从多段数据创建
var htmlBlob = new Blob(['<h1>', 'Title', '</h1>'], { type: 'text/html' });
// 从 JSON 创建
var data = { name: 'test', value: 123 };
var jsonBlob = new Blob([JSON.stringify(data)], { type: 'application/json' });
slice 方法
slice 用于截取 Blob 的一部分,返回新的 Blob 对象:
var blob = new Blob(['Hello, World!'], { type: 'text/plain' });
var partial = blob.slice(0, 5, 'text/plain');
console.log(partial.size); // 5
var reader = new FileReader();
reader.onload = function () {
console.log(reader.result); // "Hello"
};
reader.readAsText(partial);
Blob URL
通过 URL.createObjectURL() 为 Blob 生成临时 URL,可用于 DOM 元素的 src 或 href 属性:
var blob = new Blob(['body { color: red; }'], { type: 'text/css' });
var url = URL.createObjectURL(blob);
// "blob:http://localhost/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
// 使用完毕后释放内存
URL.revokeObjectURL(url);
特点:只在当前会话有效,每次调用生成新引用,需手动释放。
Blob 与 File 的关系
File 继承自 Blob,额外增加了 name、lastModified 等文件属性:
// 通过 input 获取 File
document.getElementById('fileInput').addEventListener('change', function (e) {
var file = e.target.files[0];
console.log(file.name); // 文件名(File 特有)
console.log(file.size); // 继承自 Blob
console.log(file.type); // 继承自 Blob
console.log(file.lastModified); // File 特有
// File 可以使用 Blob 的 slice 方法
var chunk = file.slice(0, 1024);
});
// 手动构造 File
var file = new File(['content'], 'test.txt', { type: 'text/plain' });
实际应用
文件下载
前端生成文件并触发下载:
function download(content, filename, type) {
var blob = new Blob([content], { type: type || 'text/plain' });
var url = URL.createObjectURL(blob);
var a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
download('Hello!', 'hello.txt', 'text/plain');
download(JSON.stringify({ a: 1 }, null, 2), 'data.json', 'application/json');
图片预览
选择图片后本地预览,无需上传:
document.getElementById('imageInput').addEventListener('change', function (e) {
var file = e.target.files[0];
if (!file.type.startsWith('image/')) return;
var url = URL.createObjectURL(file);
var img = document.getElementById('preview');
img.src = url;
img.onload = function () {
URL.revokeObjectURL(url);
};
});
分片上传
大文件利用 slice 切片后逐片上传:
function uploadByChunks(file, chunkSize) {
chunkSize = chunkSize || 2 * 1024 * 1024; // 2MB
var totalChunks = Math.ceil(file.size / chunkSize);
var current = 0;
function next() {
if (current >= totalChunks) { console.log('完成'); return; }
var start = current * chunkSize;
var chunk = file.slice(start, start + chunkSize);
var formData = new FormData();
formData.append('file', chunk);
formData.append('chunk', current);
formData.append('total', totalChunks);
formData.append('filename', file.name);
var xhr = new XMLHttpRequest();
xhr.open('POST', '/upload/chunk');
xhr.onload = function () {
current++;
console.log(Math.round(current / totalChunks * 100) + '%');
next();
};
xhr.send(formData);
}
next();
}
扩展阅读
在Blob的基础上,又衍生出一系列相关的API,用来操作文件。
- File对象:负责处理那些以文件形式存在的二进制数据,也就是操作本地文件;
- FileList对象:File对象的网页表单接口;
- FileReader对象:负责将二进制数据读入内存内容;
- URL对象:用于对二进制数据生成URL。