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;