移动端H5下载文件

前段时间遇到一个需求,需要在H5页面中增加下载文件按钮,下载一个压缩文件,第一个想到的当然是最普遍和常用的方法:动态生成a标签,把链接地址给到href属性,触发一个click事件,完美下载。于是撸起袖子就开干。

由于文件数据是通过接口请求回来的数据流,application/octet-stream类型,需要转换一下来使用:

         download() {
            let blob = res.data;
            // 请求文件数据,返回类型为blob数据流,类型application/octet-stream
            let url = window.URL.createObjectURL(blob); // 将blob转换为数据连接地址
            let a = document.createElement('a');
            a.download = 'test.zip';
            a.href = url;
            a.target = '_blank';
            document.appendChild(a);
            a.click();
            document.removeChild(a);
        }

在pc上调试时很好,下载没有任何问题,但是放到真机上就一堆问题来了:

iOS系统点击就没反应,根本没法下载,安卓手机也是几乎所有浏览器都有问题,要么下载的文件后缀不对,要么没法下载,全军覆没。

网上查了下,H5下载文件失败几乎是普遍问题,只有图片是没有兼容性问题的,长按保存本地,但是文件很多页的时候就不现实了,几乎没有什么体验可言。还有的是说ios是极度封闭的环境,下载东西很麻烦,不好处理。

于是又开始尝试其它办法

1、file-saver插件

npm i file-saver -S

使用:

import fileSaver from 'file-saver';
、、、
 let blob = res.data;
// 请求文件数据,返回类型为blob数据流,类型application/octet-stream
let url = window.URL.createObjectURL(blob); // 将blob转换为数据连接地址
fileSaver.saveAs(url,'test.zip');

结果证明效果是一样的,真机上下载不了。

2、file-saver + jszip

安装jszip:

npm i jszip -S

使用:

import jsZip from 'jszip';

import { saveAs } from 'file-saver';
、、、
let zip = new jsZip();
var myFile = zip.folder(); // 新建一个文件夹
let fileReader = new FileReader();
fileReader.onload = function(e) {
    let base64 = e.target.result;
    myFile.file('test.zip', base64, {
         base64: true
    }); // 文件名称

    zip.generateAsync({ type: 'blob' }).then(function(content) {
         // see FileSaver.js
          saveAs(content, 'test.zip');
    });
}
fileReader.readAsDataURL(blob);

效果依旧、、、失败

3、直接尝试着使用绝对地址来做测试,直接下载一个服务器上的压缩文件

download() {
   let url = htts://xxxxxx/zzz.zip; // 绝对地址
   let a = document.createElement('a');
   a.download = 'test.zip';
   a.href = url;
   a.target = '_blank';
   document.appendChild(a);
   a.click();
   document.removeChild(a);
}

真机调试,毫无兼容性问题,安卓和ios的各个浏览器都没问题,只有uc浏览器不支持打开zip文件而弹出提示,无法下载,所以思路就有了:

让后台把文件压缩好,生成一个绝对路径地址,然后把路径给到前台下载。

方法有两种:

1、文件放到七牛云上,生成绝对地址下载,但是这地址没加权限,任何人拿到都可以下载,对于合同文件类型的资源来说不够安全,放弃。

2、放到自己服务器上,依然生成绝对地址,给链接地址设置时效性,超过时间则清空服务器资源,使得下载链接无效,也可以很好的节约文件服务器资源。

3、放到自己服务器上,给链接做权限校验,前端根据后台给到的规则拼接地址,最后加上token作为权限校验

由于这个项目做了三级等保功能,讨论后决定使用第3种方案,和三级等保无缝切合。

代码:

         download() {
            let url = `${location.origin}/xxxx/${this.fileCode}?token=${this.token}`; // 拼接下载地址
            let a = document.createElement('a');
            a.download = 'test.zip';
            a.href = url;
            a.target = '_blank';
            document.appendChild(a);
            a.click();
            document.removeChild(a);
        }

这个方法虽然不能说完美,但至少能兼容绝大部分主流浏览器和移动端操作系统了,基本上能满足大部分项目的需求。

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