該來的終究是要來,今天又遇到了與之前相同的問題,就是要利用XMLHttpRequest(也就是大家熟悉的AJAX)來進行POST後,取得伺服器端打出來的二進制檔案,例如Excel、ZIP等類型的檔案。
如果你沒有特別「崎嶇」的道路要走,建議用我之前這篇文章處理,由於是採用最標準的HTML Form POST寫法,因此也最高度相容所有的瀏覽器,如果你不想沒事找事做的話,請愛用:解決AJAX Request沒有辦法收取檔案回應(檔案下載)的問題
因為目前遇到下列幾個無解的問題,進而形成死路:
而前方的死路就是,XMLHttpRequest(AJAX)只能接收文字型態的回傳訊息,除非要無視IE瀏覽器,選擇新世代支援XMLHttpRequest的responseType: blob設定之瀏覽器(請愛用:解決AJAX Request沒有辦法收取檔案回應(檔案下載)的問題)。
fetch就是叫瀏覽器幫你建立一條可以用來操作request和response的HTTP pipeline,且因為支援promise讓程式碼寫起來舒服閱讀,不像XMLHttpRequest動不動就出現波動拳程式碼...,程式碼如下請參考:
var cFileName = "YourDefaultFileName.FileExtensionName"; fetch(cUrl, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(oJSON), }) .then(oResponse => { var cContentDisposition = oResponse.headers.get("Content-Disposition"); var cNameIndexStart = "filename*=utf-8''"; var iNameIndexStart = cContentDisposition.indexOf(cNameIndexStart); if (iNameIndexStart !== -1) { cFileName = decodeURIComponent(cContentDisposition.substring(iNameIndexStart + cNameIndexStart.length)); } return oResponse.blob(); }) .then(oBlob => { var oFile = window.URL.createObjectURL(oBlob); var oLink = document.createElement("a"); oLink.href = oFile; oLink.download = cFileName; oLink.click(); window.URL.revokeObjectURL(oFile); }) .catch(oError => { alert(oError); });
程式碼中有幾點需要特別提出來說明: