node.js - NodeJs/Express 编写 xlsx-template 并将其发送回浏览器下载
问题描述
我有这个excel,我想替换xlsx-template docs说的标量值:
| Extracted on: | ${extractDate} |
我想通过响应对象发送它。该文件在输出路径中正确写入,但在客户端它给了我一个二进制输出。Bellow 是对 Url 的后端调用
this.downloadSheet = async (req, res) => {
let seriesNumber = Number(req.body.seriesNumber);
let sheetPath = path.resolve('../filePath/excel.xlsx');
let sheetFinalOuput = path.resolve('../filePath/excelOutput.xlsx');
#Get data needed to swap for the excel
let excelDataStream = await ReportService.getBalanceSheetAllInOne(balanceSheetPath, seriesNumber);
fs.readFile(path.resolve(balanceSheetPath), function(err, data) {
// Create a template
let template = new XlsxTemplate(data);
// Replacements take place on first sheet
const sheetNumber = 1;
// Perform substitution
template.substitute(sheetNumber, excelDataStream);
// Get binary data
var mydata = template.generate({ type: 'nodebuffer'});
fs.writeFile(path.resolve(balanceSheetFinalOuput), mydata, function(err) {
if(err) {
return console.log(err);
}
console.log(`Wrote data in file, check please!`);
// Send File & set headers
res.set({'Content-Disposition': `attachment; filename=balanceIncome${seriesNumber}.csv`, 'Content-Type': 'text/csv'});
res.write(mydata);
res.end();
});
});
};
客户端函数http post请求
$http.post(`${settings.apiHost}/api/panel/report/balanceSheet/allInOne/false`,{seriesNumber: $scope.seriesNumber})
.success(function (response) {
var file = new Blob([response], {type: 'text/csv'});
var isGoogleChrome = window.chrome != null && window.navigator.vendor === "Google Inc.";
var isIE = /*@cc_on!@*/false || !!document.documentMode;
var isEdge = !isIE && !!window.StyleMedia;
if (isGoogleChrome){
var url = window.URL || window.webkitURL;
var downloadLink = angular.element('<a></a>');
downloadLink.attr('href',url.createObjectURL(file));
downloadLink.attr('target','_self');
downloadLink.attr('download', `balanceSheet_${$scope.seriesNumber}.csv`);
downloadLink[0].click();
}
else if(isEdge || isIE){
window.navigator.msSaveOrOpenBlob(file,`balanceSheet_${$scope.seriesNumber}.csv`);
}
else {
var fileURL = URL.createObjectURL(file);
window.open(fileURL);
}
})
解决方案
客户端
const url = `${settings.apiHost}/api/panel/report/balanceSheet/allInOne/false/${$scope.seriesNumber}`;
window.open(url);
服务器端(将路由器参数和方法更改为 GET)
let seriesNumber = Number(req.params.seriesNumber);
...
fs.writeFile(path.resolve(balanceSheetFinalOuput), mydata, function(err) {
if(err) {
return console.log(err);
}
console.log(`Wrote data in file, check please!`);
// Send File & set headers
res.set({'Content-Disposition': `attachment; filename=balanceIncome${seriesNumber}.csv`, 'Content-Type': 'text/csv'});
res.send(mydata);
});
另一种方式
客户端
...
.success(function (nodeBuffer) {
let arraybuffer = Uint8Array.from(nodeBuffer).buffer;
var file = new Blob(arraybuffer, {type: 'text/csv'});
....
}
服务器端
...
fs.writeFile(path.resolve(balanceSheetFinalOuput), mydata, function(err) {
if(err) {
return console.log(err);
}
console.log(`Wrote data in file, check please!`);
res.send(mydata);
});
...
推荐阅读
- node.js - UnhandledPromiseRejectionWarning:错误:`receipt` 是强制性的razorpay
- c++ - CMake 时 FetchContent rabbitmq
- c# - 使用兼容的应用程序打开文件
- database - 数据建模中的 SCD-2:如何检测变化?
- jmeter - 如何执行多个 Jmeter 脚本并为这些脚本生成 html 报告
- fft - NE10定点fft中的scaled_flag是什么意思?
- c - 获取dll最小和最大堆栈地址
- liferay - Liferay 7 如何覆盖/修改/获取对 Headless API 实现的访问权限?
- c# - 如何获取与已登录用户相关的信息?
- android - 如何使用意图到达android中的特定目录