excel文件導出的方法有多種.最常見的是保存在本地或者雲服務器上在由前端去下載。這邊記錄一下思考過程。
目前公司沒有使用雲服務器,為了避免下載到本地再刪除的操作,使用二進制流進行導出。但是在使用的過程總遇到了問題,查閱資料后發現
jquery中的ajax請求,不支持二進制流。datatype格式如下: (參考地址:https://api.jquery.com/jQuery.ajax/)
由於這個原因,故使用了數據返回json格式給前端.由前端來導出.但這種方式在數據量大的時候,返回的json的格式大小會有限制,具體限制沒有進行測試
現在有新的方法,使用二進制流的方式進行excel導出. 前端使用 XMLHttpRequest 發送請求,支持流數據
代碼如下:
前端代碼:
let xhr = new XMLHttpRequest(); xhr.open("GET", url, true); // 也可以使用POST方式,根據接口 xhr.responseType = "blob"; // 返回類型blob,XMLHttpRequest支持二進制流類型 xhr.onload = function() { if (this.status === 200) { let blob = this.response; //使用response作為返回,而非responseText let reader = new FileReader(); reader.readAsDataURL(blob); // 轉換為base64,可以直接放入a標簽href reader.onload = function(e) { // 轉換完成,創建一個a標簽用於下載 let a = document.createElement("a"); a.download = "牌局查詢.xlsx"; a.href = e.target.result; a.click(); layer.msg('下載成功'); }; } else { layer.msg('下載失敗'); } }; xhr.send();
后台代碼:使用exceljs 生成二進制流文件 writeBuffer
const workbook = new Excel.Workbook(); const sheet = workbook.addWorksheet('My Sheet', { views: [{ xSplit: 1, ySplit: 1 }] }); sheet.columns = columns; if (data) { sheet.addRows(data); } sheet.eachRow((row, rowNumber) => { // 設置行高 row.height = 25; row.eachCell({ includeEmpty: true }, (cell, colNumber) => { // 設置邊框 黑色 細實線 const top = { style: 'thin', color: { argb: '000000' } }; const left = { style: 'thin', color: { argb: '000000' } }; const bottom = { style: 'thin', color: { argb: '000000' } }; const right = { style: 'thin', color: { argb: '000000' } }; cell.border = { top, left, bottom, right }; // 設置標題部分為粗體 if (rowNumber <= titleRows) { cell.font = { bold: true }; } if (cell._column._header === '牌局編號' && rowNumber > titleRows) cell.font = { color: { argb: '2828FF' } }; if (cell.text === '追殺') cell.font = { color: { argb: 'CE0000' } }; if (cell.text === '放水') cell.font = { color: { argb: '02DF82' } }; }); }); // 處理復雜表頭 if (titleRows > 1) { for (let i = 1; i < titleRows; i++) sheet.spliceRows(1, 0, []);// 頭部插入空行 for (let i = 0; i < titleRows; i++) { const row = headers[i]; for (let j = 0, rlen = row.length; j < rlen; j++) { const col = row[j]; if (!col.m1) continue; sheet.getCell(col.m1).value = col.t; sheet.mergeCells(col.m1 + ':' + col.m2); } } } const res = await workbook.xlsx.writeBuffer();
再把二進制流返回給前端:
ctx.set('Content-Type', 'application/vnd.openxmlformats'); ctx.set('Content-Disposition', "attachment;filename*=UTF-8' '" + encodeURIComponent('牌局查詢') + '.xlsx'); ctx.body = workbook;