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