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;