很多的系統管理端會有文件上傳或者下載功能,那么在文件上傳和下載的時候我們又會遇到什么樣的坑人的意外呢?
昨天我們在做管理系統的文件下載時,遇到了這么一個問題。因為文件名是后端提供,所以返回在了響應頭的Content-Disposition中,但是因為這個字段並不是默認暴露的字段,所以需要后端做暴露(加上這句代碼)
Access-Control-Expose-Headers: Content-Disposition
在前端接收到后端暴露的響應頭字段時,在請求攔截器中拿到並處理返回數據
1 service.interceptors.response.use( 2 response => { 3 if (response.request.responseType === 'arraybuffer' && !response.headers['content-disposition']) { 4 //當沒有content-disposition這個字段時return的數據 5 return response.data 6 } 7 if (response.request.responseType === 'arraybuffer' && response.headers['content-disposition']) { 8 //當存在content-disposition這個字段時,return出來的數據 9 const temp = {} 10 temp.data = response.data 11 temp.filename = response.headers['content-disposition'] 12 return temp 13 } 14 const res = response.data 15 if (res.success) { 16 return response.data 17 } else { 18 Message({ 19 message: res.message, 20 type: 'error', 21 duration: 5 * 1000 22 }) 23 return Promise.reject(res.message) 24 } 25 } 26 )
當我們下載文件時返回了文件名,下載文件模板時沒有返回文件名
1 getDocData(data) { 2 const params = { 3 id: data 4 } 5 GiftApi.exportDoc(params).then(res => { //返回文件名的寫法 6 this.content = res.data 7 const filename = res.filename.split(';')[1].split('=')[1] 8 this.filename = decodeURI(filename) 9 const blob = new Blob([this.content]) 10 if (window.navigator.msSaveOrOpenBlob) { 11 // 兼容IE10 12 navigator.msSaveBlob(blob, this.filename) 13 } else { 14 // chrome/firefox 15 const aTag = document.createElement('a') 16 aTag.download = this.filename 17 aTag.href = URL.createObjectURL(blob) 18 aTag.click() 19 URL.revokeObjectURL(aTag.href) 20 } 21 }) 22 } 23 24 getDocData(data) { 25 const params = { 26 id: data 27 } 28 GiftApi.exportDoc(params).then(res => { //未返回文件名的寫法 29 this.content = res 30 this.filename = this.temp.name + '.doc' 31 const blob = new Blob([this.content]) 32 if (window.navigator.msSaveOrOpenBlob) { 33 // 兼容IE10 34 navigator.msSaveBlob(blob, this.filename) 35 } else { 36 // chrome/firefox 37 const aTag = document.createElement('a') 38 aTag.download = this.filename 39 aTag.href = URL.createObjectURL(blob) 40 aTag.click() 41 URL.revokeObjectURL(aTag.href) 42 } 43 }) 44 }
這樣的代碼本身沒有錯誤,而且在本地和測試服務器上測試的時候也沒有問題,但是打包之后的測試會存在問題,就是未返回文件名的接口下載的文件,打開會出現[object,object],而不是我們文件原本的內容。所以我的解決方法就是讓后端統一返回文件名並把該字段暴露出來讓前端能獲取到,渲染和處理數據的格式一樣,就不會出現打包之后下載文件出錯的問題