【问题标题】:XLSX File corrupted when sent from Node.js via Restify to Client从 Node.js 通过 Restify 发送到客户端时 XLSX 文件损坏
【发布时间】:2016-12-12 23:19:59
【问题描述】:

我正在做一个项目,我正在使用 XLSX node.js 库创建一个 excel 文件,通过 Restify 将其发送到客户端,然后我使用 FileSaver.js 库将其保存在本地计算机上。当我将 xlsx 工作簿写入后端文件时,它可以正常打开,但是,当我在客户端上打开它时,它已损坏。我收到错误消息:“Excel 无法打开此文件。文件格式或文件扩展名无效。验证文件未损坏且文件扩展名与文件格式匹配”。

这是我在后端编写和发送文件的代码:

 var wopts = { bookType:'xlsx', bookSST:false, type:'binary' };
 var workbook = xlsx.write(wb, wopts);
 res.send(200, workbook);

在前端,我使用的是 XLSX 文档中的代码:

function s2ab(s) {
    var buf = new ArrayBuffer(s.length);
    var view = new Uint8Array(buf);
    for (var i=0; i!=s.length; ++i) 
        view[i] = s.charCodeAt(i) & 0xFF;
    return buf;
}

saveAs(new Blob([s2ab(response.data)],{type:""}), "test.xlsx");

关于为什么这不起作用的任何想法?任何帮助将非常感激。谢谢。

【问题讨论】:

  • 'wb' 指的是什么?看到这部分代码可能会很好。
  • 这是一个相当大的代码块,但我最终弄明白了。问题在于以二进制形式发送它,我最终使用 base64 进行编码。这个链接最终对这个问题非常有帮助:github.com/SheetJS/js-xlsx/issues/122

标签: node.js excel xlsx restify filesaver.js


【解决方案1】:

正如 Luke 在 cmets 中提到的,您必须在发送缓冲区之前进行 base64 编码。这是一个使用 NPM 模块 node-xlsx 的 sn-p。

var xlsx = require('node-xlsx');

router.get('/history', function (req, res) {
  var user = new User();
  user.getHistory(req.user.userId, req.query.offset, req.query.limit)
    .then(function (history) {
      if (req.headers.contenttype && req.headers.contenttype.indexOf('excel') > -1) {
        var data = [['Data', 'amount'], ['19/12/2016', '10']];
        var xlsxBuffer = xlsx.build([{ name: 'History', data: data }]);
        res.end(xlsxBuffer.toString('base64'));
      } else {
        res.send(history);
      }
    })
    .catch(function (err) {
      res.status(500).send(err);
    });
});

这是使用 Angular 的前端代码:

  $scope.getXlsFile = function() {
    var config = {
      params: {
        offset: $scope.offset,
        limit: $scope.limit
      },
      headers: {
        'contentType': 'application/vnd.ms-excel',
        'responseType': 'arraybuffer'
      }
    };
    $http.get('/api/history', config)
      .then(function(res) {
        var blob = new Blob([convert.base64ToArrayBuffer(res.data)]);
        FileSaver.saveAs(blob, 'historial.xlsx');
      })
  }

其中convert 是以下工厂:

.factory('convert', function () {
  return {
    base64ToArrayBuffer: function (base64) {
      var binary_string = window.atob(base64);
      var len = binary_string.length;
      var bytes = new Uint8Array(len);
      for (var i = 0; i < len; i++) {
        bytes[i] = binary_string.charCodeAt(i);
      }
      return bytes.buffer;
    }
  }
})

【讨论】:

    猜你喜欢
    • 2010-12-26
    • 2020-10-22
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-12
    相关资源
    最近更新 更多