h5下载文件,无兼容问题~

最近写了个页面,打开页面出现文件列表,用户可以下载文件。

失败方案

使用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:下载下来的文件名,可根据下载文件类型自行修改

h5下载文件,无兼容问题~_第1张图片

加上这个响应头后,访问链接就是直接下载,所以我们直接访问链接就可以,无需做其他操作,代码如下:

	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浏览器

到这里并未完全解决批量下载文件的功能,如有指教欢迎评论~

你可能感兴趣的:(前端,javascript)