HapiJS:通过浏览器下载损坏的文件 - 通过Curl工作

时间:2017-08-15 14:41:25

标签: node.js curl download hapijs exceljs

我正在努力解决HapiJS 11.1.4的问题并使用流回复为浏览器提供文件服务。结果下载已损坏。

主要端点是/api/library/export,并使用ExcelJS生成包含XLSX文件数据的流,然后我回复。

使用Curl访问时,此端点按预期工作,不会发生损坏。它纯粹只是我遇到问题的浏览器。

/api/library/export端点的代码:

handle(request, reply) {
  // Invoke XLSX generation and reply
  mapRecordsToXlsx(xlsxOpts).then(stream => {
    console.log(stream.length);
    return reply(stream)
    // .type('application/octet-stream')
    // .type('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
    // .header('Content-Disposition', 'attachment; filename=library-export.xlsx;')
    // .header('Content-Length', stream.length)
    // .encoding('binary')
    // .encoding(null)
  });
}

正如您所看到的,我已经尝试过各种响应标头组合,但无济于事。

mapRecordsToXlsx的代码:

export function mapRecordsToXlsx(opts) {
  const workbook = new Excel.stream.xlsx.WorkbookWriter();
  workbook.created = new Date();
  workbook.modified = new Date();

  // Iterate through each set of mappings and records
  opts.forEach(({title, mappings, types, records}) => {
    // Create a worksheet for the current set
    const sheet = workbook.addWorksheet(title);
    // Set column headers from mapping
    const headers = Object.keys(mappings);
    sheet.columns = headers.map(header => {
      return { header, key: mappings[header] };
    });

    // Generate rows for each record in the current sheet
    records.forEach(record => {
      const row = {};
      headers.forEach(header => {
        let value = _.get(record, mappings[header]);
        // Detect custom types and apply appropriate transformations
        if (types[header]) {
          switch (types[header]) {
          case 'date':
            value = new Date(Date.parse(value)); // ExcelJS wants a Date object
            break;
          default:
            break;
          }
        }
        row[mappings[header]] = value;
      });
      sheet.addRow(row).commit();
    });

    sheet.commit();
  });

  return workbook.commit().then(() => {
    return workbook.stream.read();
  });
}

而且,在接收方(EmberJS):

  exportAll() {
    const searchString = this.get('searchString');
    if (searchString.length > 0) {
      this.set('loading', true);
      this.get('library').exportAll(searchString)
      .then(xlsx => {
        this.set('loading', false);
        const fileName = `Library - ${searchString}.xlsx`;
        // Hack to force download of file
        const a = document.createElement('a');
        document.body.appendChild(a);
        a.style = 'display: none';
        const blob = new Blob([xlsx], {type: 'octet/stream'});
        const url = window.URL.createObjectURL(blob);
        a.href = url;
        a.download = fileName;
        a.click();
        window.URL.revokeObjectURL(url);
        return a.parentNode.removeChild(a);
      });
    }
  }

this.get('library').exportAll(searchString)纯粹是对Ember.$.ajax()的抽象,它解析/拒绝承诺。

结果文件的比较,浏览器(左)与卷曲(右):

A comparison of the resulting files: browser (left) vs curl (right)

编码看起来不对,但我无法弄清楚它是如何发生的。

这也可以帮助你帮助我:

HTTP/1.1 200 OK
vary: origin,accept-encoding
access-control-allow-origin: http://localhost:4200
access-control-expose-headers: WWW-Authenticate,Server-Authorization
content-type: application/octet-stream
cache-control: no-cache
content-length: 10157
accept-ranges: bytes
Date: Tue, 15 Aug 2017 13:49:50 GMT
Connection: keep-alive

Content-Length与HapiJS记录的内容相匹配。

0 个答案:

没有答案