2

我正在努力解决 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()将解析/拒绝作为一个承诺。

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

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

编码看起来不对,但我不知道它是如何发生的。

这也可以帮助您帮助我:

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 记录的内容相匹配。

4

0 回答 0