NodeJs/Express 编写 xlsx 模板并将其发送回浏览器下载
Posted
技术标签:
【中文标题】NodeJs/Express 编写 xlsx 模板并将其发送回浏览器下载【英文标题】:NodeJs/Express writing xlsx-template and sending it back for browser download 【发布时间】:2019-09-26 14:10:30 【问题描述】:我有这个 excel,我想将标量值替换为 xlsx-template 文档所说的:
| 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);
)
【问题讨论】:
res.write? res.send 是你需要的expressjs.com/en/api.html#res.send 我试过了,我也试过 res.sendFile(path.resolve('dataPath.xlsx'));下载文件乱了 我会将此 api 更改为 GET 方法并使用 window.open 下载它,而不是 blob 链接。如果必须这样做,请尝试***.com/a/14737423/11303576 解决响应类型问题。 我忘记 res.send(buffer) 不需要将 header 作为文件发送,删除它以防止 $http.post 对其进行解码,然后尝试将 nodebuffer 转换为 arraybuffer,并通过 arraybuffer 构建 blob 你介意发布一个更具体的例子吗?或者多解释一下一般流程? 【参考方案1】:客户端
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);
);
...
【讨论】:
第一个解决方案就像一个魅力!出于某种原因,我在 excel 中有不同的二进制输出。无论哪种方式,感谢您抽出时间并回答。我需要 url 端点是安全的,用于内部身份验证。我可以发送带有窗口对象的 http 标头吗?我认为在这种情况下,解决方案 2 效果最好。我会努力让它发挥作用。谢谢 不,window.open 方法不接受自定义标题。解决方案 2 点是 @feecks 您从服务器输出的内容以及您在浏览器中获得的内容,浏览器是否可以读取该缓冲区?如果没有,如何让它读取,转换成什么?如何将缓冲区转换为blob?这可能需要一些时间来尝试。希望这些提示对您有所帮助。 感谢您的帮助!以上是关于NodeJs/Express 编写 xlsx 模板并将其发送回浏览器下载的主要内容,如果未能解决你的问题,请参考以下文章
Nodejs / Express:错误:无法在视图目录中查找视图“错误”
nodejs+express使用ejsexcel做复杂导出Excel