zoukankan      html  css  js  c++  java
  • vue项目中用axios通过post请求下载的excel文件,以及下载的excel文件打开为乱码的解决办法

    第一次碰到下载文件用 post 的方法,之前都是用 get 方法,直接下载一个存在在服务器根目录下的文件。但是有时候碰到参数的数据量比较大的时候, get 方法就不合适了。这次后端定义的是 post 方法,返回给前端的是一个文件流。

    get 方法这里不赘述,基本思路就是动态创建一个a标签,设置a标签的 href 属性为接口地址,动态传参,下载即可。

    post 方法请求下载文件

    直接上代码:

    methods:{
      //导出模板
      exportTem(){ //最初的方法
        let url="/pmkpi/v1/restapi/file/download";  //后端的接口
        let param = this.downloadPam;  //我自己项目中的请求参数
        axios.post(url,param,{
          // responseType: 'arraybuffer'
          'responseType':'blob'
          }
        ).then(res=>{
          console.log('res=>',res); 
          if(res.status==200){
            this.exportFile(res)
          }else{  
            this.$message({
              message: '服务器错误',
              type: 'error',
              duration:2000
            });
          }
        }) 
      },
      exportFile(result){
        let contentDisposition = result.headers['content-disposition'];
        // 这里后端给的内容中,文件名字可能是驼峰式名称的 fileName ,或者是全部小写的 filename
        let filename = decodeURI(contentDisposition.split('fileName=')[1] || contentDisposition.split('filename=')[1]);
        // 注意这里的 result.data ,如果只传 result 的话,最后下载出来的excel文件,里面显示的是 [object Object]
        let blob = new Blob([result.data],{type: result.headers['content-type']});
        // let blob = new Blob([result.data],{type: "application/x-msdownload;charset=GBK"});
        // let blob = new Blob([result.data],{type: "application/x-msdownload"});
        // let blob = new Blob([result.data]);
        // let blob = new Blob([result.data],{type: "application/vnd.ms-excel"});
        let url = window.URL.createObjectURL(blob);
        if (window.navigator.msSaveBlob) {  //IE
          try {
            window.navigator.msSaveBlob(blob, filename);
          }
          catch (e) {
            console.log(e);
          }
        }
        else {  //非IE
          let link = document.createElement('a');
          link.style.display = 'none';
          link.href = url;
          link.setAttribute('download', filename);
          document.body.appendChild(link);
          link.click();
        }
        URL.revokeObjectURL(url); // 释放内存
      }
    }

    个人注解:

      1、代码写法都是自己上网搜的,参考了很多文章,基本都是这样的编码思路。

      2、post 方法请求错误的处理方法,是我自己随便写的,如果想对错误处理更详细的话可以参照另一篇文章:axios+post下载文件,以及接口报错处理

    踩坑

    代码写完之后,excel 文件也下载下来了,但是打开 excel 文件,显示的是乱码,如下图:

    自己采用 postman 测试,下载下来的文件是正常的:

    postman下载的文件显示是正常的,如下图:

     

    排查原因

    post 请求成功之后,后端返回的结果为文件流,如下图:

     在代码中把请求结果通过 console.log() 打印出来查看,结果如图:

    上网搜了很多文章,几乎都是说要设置 responseType 值为 blob ,也有设置为 arraybuffer 的,我代码里面都设置了;

    也有在  let blob = new Blob([result.data],{type: result.headers['content-type']}) 中加 type ,我看网上很多 type 值为  application/vnd.ms-excel ,但是这一次后端返回的是 application/x-msdownload ,我就把这两种都加上,一一测试,不管用什么方法改动代码,下载的excel 都是乱码。

    最后在 vue axios 请求二进制流excel文件,response乱码  这片文章中,看网友的最后一个评论,才意识到可能是 mockjs 引起的,mock 把请求返回结果类型给修改了。这个问题在之前的文章中(https://www.cnblogs.com/zyt-it/p/12206887.html) 看到过,只是没有在意。

    最后把项目中的 mock 模式关闭,一般在 main.js 文件中引入的有 mock,找到引入的代码,注释掉即可。

    再次请求,看后端返回的结果:

    mock 模式关闭后,后端返回的结果类型为 XMLHttpRequest ,之前没有关闭 mock 模式的时候,后端返回的结果类型被改为了 MockXMLHttpRequest

    此时下载的 excel 打开已经不是乱码了。

    总结:

      1、最重要的是代码中要设置 responseType 的值,无论设置 blob 或者 arraybuffer 都可以。

      2、设置 responseType 后,代码 new Blob([result.data]) 中是否设置 type 值已经不重要了,即使不设置,也可以下载文件。如果设置的话:

        可以根据后端的字段动态设置:new Blob([result.data],{type: result.headers['content-type']}) 

        也可以根据后端返回的值写死:new Blob([result.data],{type: "application/x-msdownload;charset=GBK"})

        也可以不要编码:new Blob([result.data],{type: "application/x-msdownload"})

        也可以忽略后端的返回值,直接设置:new Blob([result.data],{"application/vnd.ms-excel"})

        总之:只要加了 responseType ,这里的 type 怎么写已经无所谓了。

      3、划重点了!!!!如果依照上面的写法,下载的 excel 依然是乱码,就要看 vue 项目中是否引入了 mockjs,取消掉即可,取消 mock 模式之后,excel 文件打开就不会是乱码了。

     

     

  • 相关阅读:
    Quartz2D复习(三) --- 涂鸦
    Quartz2D复习(二) --- 手势解锁
    Quartz2D复习(一)--- 基础知识 / 绘制线段圆弧 / 图片水印 / 截图
    控制器和应用数据存储
    UIApplication
    setTimeout和setInterval
    工作中碰到的js问题(disabled表单元素不能提交到服务器)
    通知
    UITableViewController和延时执行、自定义控件
    将博客搬至CSDN
  • 原文地址:https://www.cnblogs.com/smile-fanyin/p/15079599.html
Copyright © 2011-2022 走看看