如果你用过**Maga 网盘**,那你可能发现它的文件下载方式不是直接用浏览器下载,而是先在网页中下载,下载完成后才调起浏览器的下载,比较酷。
原理就是它用了 blob 进行文件的下载之后再输出出来。我朋友 ZJINH 写了一个网盘软件中就实现了这个功能,他在群里讨论这个功能的同时也分享了代码,我的友链中有他的博客地址,欢迎大家访问(还能白嫖到他网盘客户端的源码)。
运行效果
代码如下
实现
function download(url, progress, callback, error) {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.abort();
xhr.addEventListener(
'progress',
function (e) {
if (e.lengthComputable) {
progress && progress(e.total, e.loaded);
}
},
false
);
xhr.responseType = 'blob';
xhr.onload = () => {
if (xhr.status === 200) {
callback(xhr.response);
}
};
xhr.onerror = (e) => {
error && error(e);
};
xhr.send();
return xhr;
}
代码很好看,这儿不多做分析,关键的地方是 xhr.responseType = 'blob';
用 blob 的方式获取资源。
补充
他没有给出全部的代码,callback
返回的是一个 blob
对象,我这儿补充一下。让代码跑起来
function blobDownload(blob, fileName) {
let a = document.createElement('a');
a.style = 'display: none';
document.body.appendChild(a);
let url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
}
运行
let url = 'https://files.itnote.me/d/Software/npp.7.8.5.Installer.exe';
download(
url,
(total, loaded) => {
console.log('total, loaded', total, loaded);
},
(callback) => {
console.log('callback', callback);
blobDownload(callback, 'npp.7.8.5.Installer.exe');
}
);