首页 > 解决方案 > 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);
          }
        })

标签: node.jshttpdownloadclient

解决方案


客户端

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);
});
...

推荐阅读