最近写了个页面,打开页面出现文件列表,用户可以下载文件。
失败方案
使用a标签进行下载,参考代码如下:
因为有批量下载的需求,这里将xhr请求单独封装到downloadFile.js中
// downloadFile.js
const downloadFile = (url, onProgress, xhrAr) => {
console.log(url,'urlurl');
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhrAr.push(xhr) // 存放下载任务
xhr.onprogress = (event) => { // 进度条
onProgress(event);
// if (event.lengthComputable) {
// const percent = Math.round((event.loaded / event.total) * 100);
// onProgress(percent);
// }
};
xhr.onload = () => {
if (xhr.status === 200) {
const blob = xhr.response;
resolve(blob);
} else {
reject(new Error('下载失败'));
}
};
xhr.onerror = () => {
reject(new Error('下载失败'));
};
xhr.send();
});
}
页面使用,代码如下:
const click = () => {
list.forEach((item, index) => { // 文件数组,批量下载
console.log(item, 'itemitem');
let url = serverAPIPrefix + item.filePath
const onProgress = (event) => { // 进度条处理事件
console.log(item, 'itemitem');
};
downLoadFile(url, onProgress, dlm.currentTaskList).then((blob) => {
// 处理下载完成的文件
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = item.road ? item.road : '护驾文件管理' + Date.now();
document.body.appendChild(a);
a.click();
URL.revokeObjectURL(url);
}).catch((error) => {
console.error('下载失败', error);
});
})
}
可以看到,就是用了a标签进行下载。
完成之后pc端没问题,在进行移动端测试时,发现有些浏览器不支持
浏览器 | 是否可以下载 |
---|---|
safari | 是 |
华为自带浏览器 | 是 |
vivo自带 | 是 |
oppo自带 | 否 |
uc浏览器 | 否 |
qq浏览器 | 否 |
百度浏览器 | 否 |
测试如上,具体表现为,创建了下载任务,但进度条一直是0%
成功方案
需要后端添加响应头信息,具体可查看 MDN链接
Content-Disposition: attachment; filename=326.mp4
filename:下载下来的文件名,可根据下载文件类型自行修改
加上这个响应头后,访问链接就是直接下载,所以我们直接访问链接就可以,无需做其他操作,代码如下:
let url = item.filePath
window.open(url)
如果只是单文件下载,直接使用window.open打开url,就会自行执行下载。
移动端会在浏览器中自行创建下载任务,用户可在浏览器的下载管理中查看
但是我们还有个需求,就是批量下载,循环setimeout使用window.open?经过测试,也存在浏览器的差异,下载视频下不全,选择了三个视频下载,结果只下载了两个,有的浏览器还是只能下载一个
list.forEach(item,index)=>{
setTimeout(() => {
window.open(item.url)
}, index * 1000);
})
既然访问链接直接进行下载,我们只需要打开页面就行,window.open
也是同理,但是浏览器为了防止开发人员不断打开新页面,所以window.open
是禁止循环调用,打开多个页面使用iframe
代码如下:
let triggerDelay = 100;
let removeDelay = 1000;
this.urlList.forEach((url, index) => {
this.createIFrame(url, index * triggerDelay, removeDelay);
});
// 这里是创建iframe的方法
function createIFrame(url, triggerDelay, removeDelay) {
//动态添加iframe,设置src,然后删除
setTimeout(function() {
var frame = document.createElement("iframe");
frame.src = url;
frame.style.display = "none";
document.body.appendChild(frame);
setTimeout(function() {
frame.remove();
}, removeDelay);
}, triggerDelay);
},
原文链接点击直达
使用iframe仍有部分浏览器不支持
浏览器 | 是否支持 |
---|---|
百度浏览器 | 是 |
UC浏览器 | 是 |
oppo自带浏览器 | 否 |
华为自带浏览器 | 否 |
vivo自带浏览器 | 是 |
safari | 否 |
QQ浏览器 | 否 |
到这里并未完全解决批量下载文件的功能,如有指教欢迎评论~