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 文件打开就不会是乱码了。

 

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM