我正在努力解决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()
的抽象,它解析/拒绝承诺。
结果文件的比较,浏览器(左)与卷曲(右):
编码看起来不对,但我无法弄清楚它是如何发生的。
这也可以帮助你帮助我:
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记录的内容相匹配。