Ajax處理文件流下載
文件流下載封裝
/* * AJAX請求 后端返回文件流下載處理 * @param {object} option 下載請求選項配置 * @param {string} option.method 請求方式 POST|GET etc. * @param {string} option.url 請求地址 * @param {string} option.filename 文件下載名稱 * @param {number} option.timeout 請求超時時間 單位:毫秒 * @param {function} option.beforesend 請求發送前回調 * @param {function} option.ontimeout 請求超時回調 * @param {function} option.onprogress 請求響應體下載進度回調 * @param {function} option.innererror 接口內部自定義錯誤回調 * @param {function} option.outererror 接口外部異常回調 狀態碼非200的異常 * @param {function} option.error 接口異常回調 * @param {function} option.onresponsestart 響應開始傳輸回調 * @param {function} option.complete 響應傳輸結束|請求結束 回調 */ function download(option){ var xhr=new XMLHttpRequest(); xhr.responseType='blob';//只有異步請求才能設置responseType,否則報錯,所以這里只能是異步(存疑) xhr.open(option.method, option.url, true); //打開連接 //請求發生之前回調 if(typeof option.beforesend==='function') { option.beforesend(xhr); } //下載請求超時設置 if(typeof option.timeout==='number') { xhr.timeout=option.timeout; } //下載超時回調 xhr.ontimeout=typeof option.ontimeout==='function'?option.ontimeout: function(e){ console.error('request timeout.'); }; //下載進度回調 if(typeof option.onprogress==='function') { xhr.onprogress=option.onprogress; } //請求成功回調 xhr.onload=function(){ if(this.status===200) { var data = this.response; if(data.type.indexOf('application/json')>-1){ var reader=new FileReader(); reader.readAsText(data,'UTF-8'); reader.onload=function(){ try{ var res=JSON.parse(reader.result); typeof option.innererror==='function'? option.innererror(res): console.error(res); } catch(e){ console.error(e); } } } else { /* 獲取后臺的下載文件名:如果跨域時Content-Disposition默認前端不給讀取,需要后端API操作暴露給前端 */ var disposition = decodeURI(xhr.getResponseHeader("Content-Disposition")) ,filename=option.filename||getFilenameFromDisposition(disposition) ,mimetype=xhr.getResponseHeader("Content-Type") //保存為文件下載 saveAsFile(data, filename,mimetype); } } else { typeof option.outererror==='function'?option.outererror(xhr.status,xhr.statusText,xhr.response): console.error(xhr.status,xhr.statusText,xhr.response); } } //請求異常時觸發,一般網絡狀態異常不通時會觸發,例如:網絡斷開、無法連接目標服務器等 xhr.onerror=typeof option.error==='function'?option.error: function(e){ console.error('an error has occured.'); }; //響應數據開始傳輸 if(typeof option.onresponsestart==='function') { xhr.onloadstart=option.onresponsestart; } //響應數據傳輸完成 if(typeof option.complete==='function') { xhr.onloadend=option.complete; } //發生請求數據 xhr.send(option.payload || {}); } /* * 將二進制流數據轉換成具體文件下載 * @param {blob} data 二進制流數據 * @param {string} filename 文件下載名稱 * @param {string} mimeType 文件MIME類型 */ function saveAsFile(data,filename,mimeType) { //兼容ie if ('msSaveOrOpenBlob' in navigator) { var blob = new Blob([data], { type: mimeType }); window.navigator.msSaveOrOpenBlob(blob, filename); } else { var blob = new Blob([data], { type: mimeType }); var url = window.URL.createObjectURL(blob); var link = document.createElement('a'); document.body.appendChild(link); link.style.display = 'none'; link.download = filename; link.href = url; link.click(); window.URL.revokeObjectURL(url);//手動釋放blobURL,避免內存溢出 document.body.removeChild(link); } } /* * 獲取文件下載名稱 * @param {string} disposition 請求響應頭中的Content-Disposition */ function getFilenameFromDisposition(disposition){ var filename=''; if (disposition && disposition.indexOf('attachment') !== -1) { var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/; var matches = filenameRegex.exec(disposition); if (matches != null && matches[1]) { filename = matches[1].replace(/['"]/g, ''); } } return filename; }
示例
download({ method:'POST', url:'http://192.168.1.2/api/file/download', payload:JSON.stringify({ "page": 1, "limit": 60000, "data": { sdate:'2023-10-01', edate:'2023-10-31' } }), filename:'西游記.xlsx', beforesend:function(xhr){ xhr.setRequestHeader("content-type", "application/json;charset=UTF-8"); }, innererror:function(res){ console.error(res.msg); }, onresponsestart:function(e){ console.log('文件流開始傳輸'); }, onprogress:function(event){ if(event.lengthComputable){ var percentage=(event.loaded/event.total).toFixed(4)*100; percentage+='%'; console.log(percentage); } }, complete:function(status,statusText,responseText){ console.log('請求結束'); } });
浙公網安備 33010602011771號