前端JS 下載大文件解決方案

問題場景

點擊導出按鈕,提交請求,下載excel大文件(超過500M),該文件沒有預生成在後端,
直接以文件流的形式返回給前端。前端

解決方案

在Vue項目中經常使用的方式是經過axios配置請求,讀取後端返回的文件流,經常使用代碼以下:ios

axios({
    method: 'post',
    url: 'api/file',
    responseType: 'blob'
}).then(res=> {
     if (res.data){
      filename = 'filename';
      let blob = new Blob([res.data],{type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"});
      if (window.navigator.msSaveOrOpenBlob){
          // IE10+下載
        navigator.msSaveOrBlob(blob, filename);
      }else{
          // 非IE10+下載
        let link = document.createElement('a');
        link.href = window.URL.createObjectURL(blob);
        link.download = filename;
        document.body.appendChild(link);
        var evt = document.createEvent("MouseEvents");
        evt.initEvent("click", false, false);
        link.dispatchEvent(evt);//釋放URL 對象
        document.body.removeChild(link);
      }
}).catch((error) => {
  console.log(error)
})

這種方式是把文件流讀取到瀏覽器內存中,再下載,可是今天在這種大文件場景下它不香了,
因爲內存過大,直接把網頁給搞崩了,喔豁😂git

怎麼辦呢,終於在Github上找到了一個大神的庫,用起來真香,Github地址github

根據介紹,在chrome瀏覽器2G如下的文件下載能夠獲得很好的支持chrome

使用步驟

1.安裝npm依賴

npm install file-saver --savenpm

2.引入代碼

+ import { saveAs } from 'file-saver';
...
+      saveAs(blob, fileName );

3.完整例子

+ import { saveAs } from 'file-saver';
  axios({
    method: 'post',
    url: 'api/file',
    responseType: 'blob'
}).then(res=> {
     if (res.data){
       fileName = this.fileName;
      // 有文件名就用自定義的,沒有就從header獲取
        if (!fileName) {
          fileName = fileNameFromHeader(
            res.headers["content-disposition"] || ""
          );
        }
        
      let blob = new Blob([res.data],{
      type:"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8"});
+      saveAs(blob, fileName );
      }
}).catch((error) => {
  console.log(error)
})

function fileNameFromHeader(disposition) {
  let result = null;
  disposition = disposition.split(";")[1];
  if (disposition && /filename=.*/gi.test(disposition)) {
    result = disposition.match(/filename=.*/gi);
    return decodeURIComponent((result[0].split("=")[1]).replace(/\+/g, '%20'));
  }
  return "null";
}

4.其餘問題

下載大文件過程當中遇到的其餘問題axios

  • axios請求超時,注意配置timeout
  • Nginx 響應超時報504 網關超時錯誤,注意配置Nginx
  • 控制檯報error response,瀏覽器請求長時間得不到響應,本地調試代理轉發超時形成的,參考
  • 文件超過2G的解決方案
相關文章
相關標籤/搜索