今天就来聊聊Blob,到底是什么,怎么用,以及那些年我踩过的坑。
PS,最近在面试的同学,可以看看这个 前端面试题宝典这个网站,涵盖了绝大部分前端面试八股文,对复习效率提升还是比较明显的。
Blob?不就是个二进制的对象嘛
说实话,第一次听说Blob的时候,我以为是哪个新出的框架缩写。后来才知道,这玩意全称是Binary Large Object,翻译过来就是“二进制大对象”。听着挺高大上,其实说白了就是前端处理二进制数据的一个接口。
我记得最早接触Blob是在做文件上传功能的时候。那时候需要在前端先验证用户上传的是不是图片文件,就得用Blob来获取文件类型。
// 举个例子,获取用户上传的文件类型
const fileInput = document.getElementById('fileInput');
fileInput.addEventListener('change', (e) => {
const file = e.target.files[0];
console.log(file instanceof Blob); // true
console.log(file.type); // image/png
});
看到没,我们熟悉的File对象其实就是Blob的一种特殊类型,多了个name、lastModifiedDate这样的属性而已。
怎么用Blob解决实际问题的
图片压缩功能
记得有一次产品经理说要做个图片压缩上传的功能,我第一反应是“这得后端来吧”,但后端哥们那会儿正忙得焦头烂额,我就硬着头皮研究前端方案。
结果发现用Canvas压缩图片后,可以直接用toBlob()方法转换成Blob对象:
function compressImage(file, quality = 0.8) {
return new Promise((resolve) => {
const img = new Image();
img.onload = () => {
const canvas = document.createElement('canvas');
// ...省略canvas尺寸设置代码
canvas.toBlob((blob) => {
resolve(blob);
}, 'image/jpeg', quality);
};
img.src = URL.createObjectURL(file);
});
}
大文件分片上传
还有一个让我印象深刻的场景是大文件上传。用户要上传2G的视频文件,直接上传肯定不行,那时候我就用Blob的slice方法做了分片:
function sliceFile(file, chunkSize = 1024 * 1024) {
const chunks = [];
let start = 0;
while (start < file.size) {
const chunk = file.slice(start, start + chunkSize);
chunks.push(chunk);
start += chunkSize;
}
return chunks;
}
这样就把大文件切成了1MB一块的小文件,可以分片上传、断点续传了。说实话,做完这个功能后,我在团队里走路都带风。
Blob的另一个妙用:生成临时下载链接
不知道你们有没有遇到过这种需求:把页面上的数据生成文件让用户下载。我最开始的做法是让后端生成文件链接,直到有一天后端同事说:“你这前端不能自己搞定吗?”
然后我就发现了URL.createObjectURL()这个方法:
function downloadData(data, filename, type = 'text/plain') {
const blob = new Blob([data], { type });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
// 清理很重要!不然会内存泄漏
setTimeout(() => {
document.body.removeChild(a);
URL.revokeObjectURL(url);
});
}
现在Blob还能这么玩
最近我还看到一些有趣的应用场景。比如用Blob + Service Worker做资源缓存,或者配合Web Assembly处理大型二进制数据。
不过说实话,日常开发中大部分时候我们不需要直接操作Blob,很多框架都已经封装好了。但了解底层原理的好处是,当遇到棘手问题时,你能多一条解决问题的思路。
好了,今天先聊到这。如果你们在Blob使用上有什么有趣经历或者坑点,欢迎在评论区分享——我也很好奇大家都会遇到什么奇怪的问题。
对了,如果文章里有哪里没说清楚的,也可能是我记错了(毕竟工作这么多年了),欢迎指正!