前言:
egg实现后端提供下载接口,前端直接a标签调用,也可以直接用浏览器访问地址下载。
实现效果:
页面输入 http://localhost:7001/toexecl ,下载下文件,名称,样式可调整
后端:
1、安装插件 exceljs ,(附: exceljs中文api )
cnpm install exceljs --save
2、引入:
const ExcelJS = require('exceljs');
ES5 导入
const ExcelJS = require('exceljs/dist/es5');
3、app/service 新建文件 common.js 这里配置excel的具体配置
const Service = require('egg').Service;
const Excel = require('exceljs');
class CommonService extends Service {
/**
* 数据并生成excel
* @param {Array} headers excel标题栏
* @param {Array} param 数据参数
* @param {string} name 文件名称
*/
async excelCommon(headers, data, name) {
let columns = [];// exceljs要求的columns
let hjRow = {};// 合计行
let titleRows = headers.length;// 标题栏行数
// 处理表头
headers.forEach(row=>{
row.forEach(col=>{
let { f, t ,w} = col;
if (f){
if (col.totalRow) hjRow[f] = true;
if (col.totalRowText) hjRow[f] = col.totalRowText;
col.style = { alignment: { vertical: 'middle', horizontal: 'center' } };
col.header = t; //文字
col.key = f; //对应的字段
col.width = w ? w : 15;//宽度
columns.push(col);
}
})
})
let workbook = new Excel.Workbook();
let sheet = workbook.addWorksheet('My Sheet', { views: [{ xSplit: 1, ySplit: 1 }] });
sheet.columns = columns;
sheet.addRows(data);
// 处理复杂表头
if (titleRows > 1) {
// 头部插入空行
for (let i = 1; i < titleRows; i++) sheet.spliceRows(1, 0, []);
headers.forEach(row=>{
row.forEach(col=>{
if (col.m1){
sheet.getCell(col.m1).value = col.t;
sheet.mergeCells(col.m1 + ":" + col.m2);
}
})
})
}
// 处理样式、日期、字典项
sheet.eachRow(function (row, rowNumber) {
// 设置行高
row.height = 25;
row.eachCell({ includeEmpty: true }, (cell)=> {
// 设置边框 黑色 细实线
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 }; return; }
});
});
this.ctx.set('Content-Type', 'application/vnd.openxmlformats');
// 这个地方的空格不要更改
this.ctx.set('Content-Disposition', "attachment;filename*=UTF-8' '" + encodeURIComponent(name) + '.xlsx');
this.ctx.body = await workbook.xlsx.writeBuffer();
}
}
module.exports = CommonService;
4、配置路由
module.exports = app => {
const { router, controller } = app;
app.get('/toexecl', controller.new.downExcel.toexecl);
}
5、具体操作部分:controller/new/downExcel.js
const Controller = require('egg').Controller;
class downFileController extends Controller {
async toexecl() {
const { ctx } = this;
//两层数组,一层是行,一层是列,允许多行
let headers = [
[
{ t: '下单时间', f: 'trade_time', totalRow: true },
{ t: '订单类型', f: 'order_type', totalRow: true },
{ t: '手机号码', f: 'phone_number', totalRow: true },
{ t: '扫描状态', f: 'scan_status', totalRow: true },
{ t: '交易状态', f: 'ctf_order_status', totalRow: true },
{ t: '订单份额(克)', f: 'trade_share', totalRow: true },
{ t: '当时账号总份额(克)', f: 'account_share', totalRow: true ,w:25},
{ t: '订单号', f: 'order_no', totalRow: true },
]
];
let data = [
{ trade_time: '2020-12-10', order_type:'线上', phone_number:'18374009921', scan_status:'1', ctf_order_status:'1', trade_share:'2', account_share:'2', order_no:'164656456546' },
{ trade_time: '2020-12-10', order_type:'线下', phone_number:'18374009921', scan_status:'1', ctf_order_status:'1', trade_share:'2', account_share:'2', order_no:'164656456546' }
] // 需要在这边自己适配数据,这边为空
await ctx.service.common.excelCommon(headers, data, '订单信息');
}
}
module.exports = downFileController;
6、如果有具体需要,可以将data的数据,从其他方法里面,调用mysql来获取到,下面:
7、查看页面:
输入:http://localhost:7001/toexecl
可以看到下载成功了!
前端部分:
1.第一种方法:downFile(下载地址, 保存名称);
function downFile(content, filename) {
// 创建隐藏的可下载链接
var eleLink = document.createElement('a');
eleLink.download = filename;
eleLink.style.display = 'none';
// 字符内容转变成blob地址
var blob = new Blob([content]);
eleLink.href = URL.createObjectURL(blob);
// 触发点击
document.body.appendChild(eleLink);
eleLink.click();
// 然后移除
document.body.removeChild(eleLink);
};
2.第二种方法:
<a href="/api/getImg" download="file.xlsx">下载</a>