有些項目導出功能是通過Blob對象實現的,代碼差不多可能大概類似長這個樣子:
var params={ XX:xx, } this.$axios.get('/XXX/XXX',{ params: params, responseType: 'blob' }).then(res => { console.log(res); });
其中,關鍵語句就是responseType。它表示的是服務器響應的數據類型,正常能獲取到的響應體res打印出來大致是這樣的,如圖1所示:
圖1 正確的Blob對象
但是如果設置了responseType還是獲取不到正常的Blob對象,控制台打印出來類似下面這樣的亂碼,如圖2所示:
圖2 “不正常”的Blob對象,出現亂碼
然后下載下來的文件也是提示損壞,如圖3,4,5所示
圖3 都是騙人的,修復也是木有用滴
圖4 提示下載文件報錯
圖5 亂碼格式下載的文件打開后為空白
如果后端走Postman是可以成功下載排除了是后端的鍋的話,這個時候就要注意前端項目中是否用了mock模塊。mock.js原本是為了攔截請求,生成隨機數據,讓前端獨立於后端進行開發。但是打開node_modules下mockjs的mock.js源碼,大概在8400行左右有這樣一段代碼,如圖6所示。可以看到這個方法是用來初始化Response的,只要項目里包含了這個模塊,每次項目啟動初始化的時候,就會給響應攔截的responseType修改為' '。所以導致了我們原先設置的responseType:'blob'無效,也就進而導致了接收二進制流出現亂碼。
圖6 mock.js源碼初始化Response的方法
當時,我們接收到亂碼之后,前端查,后端查,后端查完,前端查,前后端都找了很久,就是沒有找到問題所在。我反復看了Axios和WebAPI官方文檔中關於Blob對象的相關配置,我覺得我的前端代碼肯定沒有問題,但是后端也通過走Postman已經排除了自己的“嫌疑”,所以,這個鍋還得前端背。我當時覺得既然不是這一塊代碼的問題,是不是因為某種東西改變了響應頭的結構,這樣就很容易想到axios里的響應攔截器,但是查看了下並沒有這樣的代碼。然后就面向百度編程,終於在思否論壇里找到一個可能性:mock模塊會影響原生的ajax請求,使得服務器返回的blob類型變成亂碼。貼上原文地址:https://segmentfault.com/q/1010000014704618/。瞬間豁然開朗,打開入口文件main.js,注釋掉相關代碼,僅僅兩個“//”,立馬解決問題,如圖7所示。
圖7 在main.js中注釋掉引入mock模塊的代碼
其實思路是正確的,但是很容易想到是axios實例的響應攔截器,卻沒有想到是mock!!