项目中的功能:通过点击【导出】按钮,将列表的数据转成excel文件导出。这个功能有多种处理方法,我这边分为Node(后端)+前端联合处理、纯Node(后端)处理
一、Node+前端
在Node层直接将数据处理成前端生成excel文件时需要的数据格式,然后将生成excel文件的方法封装(exportXlsx)之后,调用node层的接口获取数据之后直接传给exportXlsx
const xlsx = require('node-xlsx');
//exportXlsx方法
function exportXlsx(worksheets, fileName = '测试') {
const result = xlsx.build(worksheets);
const ab = Buffer.from(result, 'binary');
const blob = new Blob([ab]);
const blobUrl = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = blobUrl;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(blobUrl);
}
注意:worksheets的数据格式:[{ name: 'Sheet1', data:[['表头1','表头2','表头3'],['第1行第1列内容','第1行第2列内容','第1行第3列内容']] }]
二、纯Node端
直接在node层将文件流传输给客户端,这种处理方式也有两种方法
1、一种是使用node-xlsx
创建了一个excel文件,然后将其保存到本地,最后将其发送给前端。
这种方法因为使用fs.createReadStream()是读取本地文件流的,因此
需要将excel文件保存到本地,并将其作为流传输到客户端,会造成磁盘空间的浪费和读写磁盘的开销,因此不推荐,了解即可。
import fs from 'fs';
import path from 'path';
import xlsx from 'node-xlsx';
export default (req, res) => {
// 创建一个excel文件
const data = [
['姓名', '年龄', '性别'],
['张三', 18, '男'],
['李四', 20, '女'],
['王五', 22, '男'],
];
const buffer = xlsx.build([{ name: 'Sheet1', data: data }]);
// 将excel文件保存到本地
const filePath = path.join(__dirname, 'example.xlsx');
fs.writeFile(filePath, buffer, (err) => {
if (err) {
console.log(err);
return res.status(500).send('导出失败');
}
// 将excel文件发送给前端
res.setHeader('Content-disposition', 'attachment; filename=example.xlsx');
res.setHeader('Content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
const filestream = fs.createReadStream(filePath);
filestream.pipe(res);
});
};
2、另一种是使用stream.PassThrough用来创建一个简单的流传递器,即把输入数据原封不动地传递到输出中,不做任何处理。这个方法使用new stream.PassThrough()
是创建一个 PassThrough
流对象,然后将该对象作为参数传递给 xlsx.build()
方法,将 Excel 数据写入这个可写流中,以生成二进制数据。该方法不需要将文件写入磁盘,而是直接将二进制流数据通过内存中的流来传输,因此可以避免磁盘空间的浪费和读写磁盘的开销。一般推荐。
// /api/exportExcel.ts
import xlsx from 'node-xlsx';
import stream from 'stream'
export default (req, res) => {
// 创建一个excel文件
const data = [
['姓名', '年龄', '性别'],
['张三', 18, '男'],
['李四', 20, '女'],
['王五', 22, '男'],
];
const buffer = xlsx.build([{ name: 'Sheet1', data: data }]);
// 将excel文件发送给前端
res.setHeader('Content-disposition', 'attachment; filename=example.xlsx');
res.setHeader('Content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
const filestream = new stream.PassThrough();
filestream.end(buffer);
filestream.pipe(res);
};
3、还有一种更简单的方法是直接使用 node-xlsx
提供的 build
方法生成 Excel 文件的二进制流数据,然后通过 res.end()
方法将该二进制流数据返回给客户端(推荐)
import { build } from 'node-xlsx';
export default function handler(req, res) {
// 创建 Excel 数据
const data = [
['姓名', '年龄', '性别'],
['张三', 18, '男'],
['李四', 20, '女'],
['王五', 22, '男'],
];
// 构造一个 Excel 文件对象
const excelFile = [
{
name: 'sheet1',
data: data,
},
];
// 生成 Excel 文件的二进制流数据
const buffer = build(excelFile);
// 设置响应头
res.setHeader(
'Content-Type',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
);
res.setHeader('Content-Disposition', 'attachment; filename=test.xlsx');
// 将 Excel 文件的二进制流数据返回给客户端
res.end(buffer, 'binary');
}