多文件pc端 移动端web下载 js+vue 实现

问题
① 后端返回值是文件流
② 移动端点击无效
③ 多种类型的文件下载 pdf png doc xls 等
④ pc端,安卓端,苹果端
⑤ 无状态码,如何判断是文件流还是传失败了

思路:
① 请求后端获取文件流
② 将文件流转换为blob链接
③ blob链接转化时要注意添加mime类型
(移动端不加此步会导致下载失效)
④ js创建一个a标签,并触发click点击下载

整体代码放在后面,新手试错,有问题请友善交流

效果:

pc端:
在这里插入图片描述
安卓端(不同的浏览器效果不同):
在这里插入图片描述
苹果端:
直接会新跳转一个页面进行预览,此处未截图

一、首先介绍mime
浏览器通常使用MIME类型(而不是文件扩展名)来确定如何处理URL,因此Web服务器在响应头中添加正确的MIME类型非常重要。如果配置不正确,浏览器可能会曲解文件内容,网站将无法正常工作,并且下载的文件也会被错误处理。
详细介绍以及类型见mdn
链接: MIME
在这里插入图片描述
二、文件流转blob链接
所谓的文件流就是后端直接把图片或者其他文件通过流的形式发送给前端(后端也可能发送文件链接,视具体情况而定)
文件流形式
在这里插入图片描述
此处因为后端直接传的文件流,没有传状态码,所以视情况更改代码

let content = data;//arraybuffer类型数据
          let resBlob = new Blob([content]);
          let reader = new FileReader();
          reader.readAsText(resBlob, 'utf-8');
          reader.onload = () => {
            try { // 判断是否可以转化为json格式,可以就说明不是文件流,错误返回值
              let res = JSON.parse(reader.result);
              console.log(res);
              this.$message.destroy();
              this.$message.error(res.message);
            } catch { // 报错说明不能转化为json,是文件流,下载文件
              console.log('res status', data);
              // let blob = new Blob([data]); // 原 此种方式在pc端可以下载,但是手机端不行
              let blob = new Blob([data], {
                'type': fileTypeMime
              }); //
              const blobUrl = window.URL.createObjectURL(blob);
              const a = document.createElement('a');
              a.style.display = 'none';
              a.download = fileName;
              a.href = blobUrl;
              a.click();
            }
          };

三、文件下载
通过js生成一个a链接节点,绑定文件下载链接,然后触发a的click事件
download是文件名字
href链接绑定blob上文转换的blob链接(移动端下载时,blob链接要加上mime类型,pc端可加可不加)

const a = document.createElement('a');
              a.style.display = 'none';
              a.download = fileName;
              a.href = blobUrl;
              a.click();

四、完整代码

getFileById() {
        let params = {}; // 此处为向后端请求的参数
        let fileName = ''; // 此处为下载的文件名字,包括格式后缀,如 test.jpg
        let url = ''; // 此处为请求链接
        let fileTypeMime = ''; // 文件mime类型
        
         // 个人赋值
        params = { taskCommonId: this.commonId };
        fileName = this.fileUrl;
        url = `${window._CONFIG['domianURL']}trial/task/plan/common/getFileByTaskCommonId`;
        let suffix = fileName.split(); // split后获得文件后缀
        suffix = suffix[suffix.length-1];
        switch (suffix) { // switch获取后缀对应的mime 可参考上文链接
          case 'png': fileTypeMime = 'image/png'; break;
          case 'doc': fileTypeMime = 'application/msword'; break;
          case 'docx': fileTypeMime = 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'; break;
          case 'jpg': case 'jpeg': fileTypeMime = 'image/jpeg'; break;
          case 'gif': fileTypeMime = 'image/gif'; break;
          case 'svg': fileTypeMime = 'image/svg+xml'; break;
          case 'tif': case 'tiff': fileTypeMime = 'image/tiff'; break;
          case 'txt': fileTypeMime = 'text/plain'; break;
          case 'ppt': fileTypeMime = 'application/vnd.ms-powerpoint'; break;
          case 'pptx': fileTypeMime = 'application/vnd.openxmlformats-officedocument.presentationml.presentation'; break;
          case 'xls': fileTypeMime = 'application/vnd.ms-excel'; break;
          case 'xlsx': fileTypeMime = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'; break;
          case 'zip': fileTypeMime = 'application/zip'; break;
          case '7z': fileTypeMime = 'application/x-7z-compressed'; break;
        }

        this.$http({
          url: url,
          method: 'get',
          responseType: 'arraybuffer',   //一定要设置响应类型,否则文件会是空白
          params: params,
        }).then((data) => {
          let content = data;//arraybuffer类型数据
          let resBlob = new Blob([content]);
          let reader = new FileReader();
          reader.readAsText(resBlob, 'utf-8');
          reader.onload = () => {
            try { // 判断是否可以转化为json格式,可以就说明不是文件流,错误返回值
              let res = JSON.parse(reader.result);
              console.log(res);
              this.$message.destroy();
              this.$message.error(res.message);
            } catch { // 报错说明不能转化为json,是文件流,下载文件
              console.log('res status', data);
              // let blob = new Blob([data]); // 原 此种方式在pc端可以下载,但是手机端不行
              let blob = new Blob([data], {
                'type': fileTypeMime
              }); //
              const blobUrl = window.URL.createObjectURL(blob);
              const a = document.createElement('a');
              a.style.display = 'none';
              a.download = fileName;
              a.href = blobUrl;
              a.click();
            }
          };
        });
      },
GitHub 加速计划 / vu / vue
207.54 K
33.66 K
下载
vuejs/vue: 是一个用于构建用户界面的 JavaScript 框架,具有简洁的语法和丰富的组件库,可以用于开发单页面应用程序和多页面应用程序。
最近提交(Master分支:2 个月前 )
73486cb5 * chore: fix link broken Signed-off-by: snoppy <michaleli@foxmail.com> * Update packages/template-compiler/README.md [skip ci] --------- Signed-off-by: snoppy <michaleli@foxmail.com> Co-authored-by: Eduardo San Martin Morote <posva@users.noreply.github.com> 4 个月前
e428d891 Updated Browser Compatibility reference. The previous currently returns HTTP 404. 5 个月前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐