Axios發送請求下載文件(重寫二進制流文件)


用axios正常發送請求下載excel會出現以下問題,即將二級制流文件下載到了本地,下附解決辦法:

 一、實現思路:

這類方法思路如下:

1. 使用js在頁面常見a標簽

2. 創建Blob對象, 在Blob中傳入后端返回的response.data

   這一步中Blob需要的是一個數組類型的參數, 后端二進制流這邊接收到的response.data使用查看發現是String, 所以我把response.data放進一個長度1的數組, 再傳入Blob對象,

   此外需要規定文件類型, 可以是doc的(這里傳的word文檔)application/vnd.openxmlformats-officedocument.wordprocessingml.document, 也可以是二進制流的application/actet-stream

3. 創建下載鏈接 window.URL.createObjectURLblob()

4. 把3創建的鏈接變量賦值個a標簽的href屬性(這類用法詳見a標簽文檔)

5. 使用document.body.appendChild把a標簽掛上去, 再調用a標簽的.click()事件

6. document.body.removeChild(a標簽) 移除a標簽

7.window.URL.revokeObjectUR()下載鏈接)釋放blob對象

 

二、get請求下載流文件:

1、使用 responseType: 'blob' 下載文件

第一步:讓后端將下載的接口的response header設置:

Content-disposition: attachment; filename=數據報表.xlsx(表示會直接下載文件,文件名為‘數據報表’)

Content-Type:application/octet-stream  (二進制流數據,如常見的文件下載)

第二步:修改axios請求的responseType為blob,以get請求為例:

第三步:請求成功,拿到response后,調用下載函數

  //get下載
  onFileDownload = (index,item) => {
    request.get('/file/records/download', {
      params: {
        //這里是參數
      },
      responseType: 'blob',//響應類型為流
      onDownloadProgress:(ProgressEvent) => {//用來計算下載量(實際項目中可以用來顯示下載進度)
        let total = item.fileLength;
        // console.log(ProgressEvent);
        let load = ProgressEvent.loaded;
        // console.log(load);
      }
    }).then((resp:any) => {
      if(resp) {
        let blob = new Blob([resp]);
        let url = window.URL.createObjectURL(blob);
        let link = document.createElement('a');
        link.href = url
        link.download = item.fileName || '下載文件';//下載后文件名
        document.body.appendChild(link);
        link.click();//點擊下載
        link.remove();//下載完成移除元素
        window.URL.revokeObjectURL(link.href); //用完之后使用URL.revokeObjectURL()釋放;
      }else {
        Message.error('文件下載失敗,請重試!');
      }
    }).catch(e => {
      Message.error('暫無下載該文件的權限!');
    }).finally(() => {
      //請求結束回調
    })
  }

 或

download(){
  this.$http({
    method:"get",
    url:接口地址+"?data="+encodeURI(JSON.stringify(data)),
    responseType:'blob'
    }).then((res)=>{
      //這里res.data是返回的blob對象
      var blob = new Blob([res.data], {type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document;charset=utf-8'}); //application/vnd.openxmlformats-officedocument.wordprocessingml.document這里表示doc類型
        var contentDisposition = res.headers['content-disposition'];  //從response的headers中獲取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 設置的文件名;
      var patt = new RegExp("filename=([^;]+\\.[^\\.;]+);*");
      var result = patt.exec(contentDisposition);
      var filename = result[1];
      var downloadElement = document.createElement('a');
      var href = window.URL.createObjectURL(blob); //創建下載的鏈接
      downloadElement.style.display = 'none';
      downloadElement.href = href;
      downloadElement.download =filename ; //下載后文件名
      document.body.appendChild(downloadElement);
      downloadElement.click(); //點擊下載
      document.body.removeChild(downloadElement); //下載完成移除元素
      window.URL.revokeObjectURL(href); //釋放掉blob對象
    })
}

 

三、post請求下載流文件:

第一步:讓后端將下載的接口的response header設置:

Content-disposition: attachment; filename=數據報表.xlsx(表示會直接下載文件,文件名為‘數據報表’)

Content-Type:application/octet-stream  (二進制流數據,如常見的文件下載)

第二步:修改axios請求的responseType為blob,以post請求為例:

第三步:請求成功,拿到response后,調用下載函數

//文件下載
  onFileDownLoad(){
    request.post('/talent/demand/export',{
        //下載參數
      },
      {
        responseType: "blob"//指定響應類型
      }
    ).then((data:any) => {
      if(data) {
        if (!data) {
            return
        }
        let userInfo = this.getLoginNo()
        let url = window.URL.createObjectURL(new Blob([data]))
        let link = document.createElement('a')
        link.style.display = 'none'//設置隱藏創建的標簽
        link.href = url
        link.setAttribute('download', `下載文件-${(new Date()).valueOf()}-${userInfo['empName']}(${userInfo['empId']}).xlsx`)//下載文件名稱
        document.body.appendChild(link)
        link.click()//點擊下載
        link.remove();//下載后移除
        window.URL.revokeObjectURL(link.href); //用完之后使用URL.revokeObjectURL()釋放;
      }else {
        Message.error('下載出錯,請重試!');
      }
    }).catch(e => {
      Message.error('暫無下載該文件的權限!');
    })
  }

 或

download(){
  this.$http({
    method:"post",
    url: 接口url,
    data:JSON.stringify(data),
    responseType:'blob',
    headers: {
      'Content-Type': 'application/json;charset=UTF-8'    //后端ssm框架接收json類型
    }
  }).then((res)=>{
  //這里res.data是返回的blob對象
  var blob = new Blob([res.data], {type: 'application/actet-stream;charset=utf-8'});
  var contentDisposition = res.headers['content-disposition'];  //從response的headers中獲取filename, 后端response.setHeader("Content-disposition", "attachment; filename=xxxx.docx") 設置的文件名;
  var patt = new RegExp("filename=([^;]+\\.[^\\.;]+);*");
  var result = patt.exec(contentDisposition);
  var filename = result[1];
  var downloadElement = document.createElement('a');
  var href = window.URL.createObjectURL(blob); //創建下載的鏈接
  downloadElement.style.display = 'none';
  downloadElement.href = href;
  downloadElement.download =filename ; //下載后文件名
  document.body.appendChild(downloadElement);
  downloadElement.click(); //點擊下載
  document.body.removeChild(downloadElement); //下載完成移除元素
  window.URL.revokeObjectURL(href); //釋放掉blob對象
  })
}

 

四、其他下載方法:

1、下載時創建a標簽;

let formElement = document.createElement('form'); 
formElement.style.display = "display:none;"; 
formElement.method = 'post'; 
formElement.action = ${apiBasePath}/api/xxxxx/downloadDetailData; 
formElement.target = 'callBackTarget'; 
let inputElement = document.createElement('input'); 
inputElement.type = 'hidden'; 
inputElement.name = "params" ; 
inputElement.value = params; 
formElement.appendChild(inputElement); 
document.body.appendChild(formElement); 
formElement.submit(); 
document.body.removeChild(formElement);

缺點:該種方式下載傳給后端的參數類型為:"application/x-www-form-urlencoded",且不支持修改傳參類型。

 

2、get請求簡單下載:

  //get拼接下載
  tableDataExport(){
    const data = {
      ...this.state.params,
      orderType: this.state.orderType,
      pageSize: undefined,
      pageNo: undefined,
      sortBy: undefined,
    }
    let loadData:any = ''
    for (let item in data){
      if(item && data[item]){
        if(isNaN(Number(data[item]))){
          loadData += item + '=' + data[item] + '&'
        }else{
          loadData += item + '=' + Number(data[item]) + '&'
        }
      }
    }
    window.location.href = config.baseURL + '/api/xxxx?' + loadData
  }

3、瀏覽器get下載使用window.open下載

var downURL = '下載接口'  

var getData = '?starTime=20180922&endTime=20180925'

var request = downURL+getData

window.open(request)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM