node.js - HapiJS: Corrupt File Download via Browser - Works via Curl -
i'm struggling issue hapijs 11.1.4 , replying stream serve browser file. resulting download corrupt.
the main endpoint /api/library/export , uses exceljs generate stream containing data xlsx file, i'm replying with.
this endpoint works expected when accessed using curl , no corruption occurs. purely browser i'm having issues with.
code /api/library/export endpoint:
handle(request, reply) { // invoke xlsx generation , 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) }); } as can see, i've tried various combinations of response headers, no avail.
code 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 , records opts.foreach(({title, mappings, types, records}) => { // create worksheet current set const sheet = workbook.addworksheet(title); // set column headers mapping const headers = object.keys(mappings); sheet.columns = headers.map(header => { return { header, key: mappings[header] }; }); // generate rows each record in current sheet records.foreach(record => { const row = {}; headers.foreach(header => { let value = _.get(record, mappings[header]); // detect custom types , apply appropriate transformations if (types[header]) { switch (types[header]) { case 'date': value = new date(date.parse(value)); // exceljs wants date object break; default: break; } } row[mappings[header]] = value; }); sheet.addrow(row).commit(); }); sheet.commit(); }); return workbook.commit().then(() => { return workbook.stream.read(); }); } and, on receiving side (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 force download of file const = 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) purely abstraction on ember.$.ajax() resolve/rejects promise.
a comparison of resulting files, browser (left) vs curl (right):
the encoding looks wrong can't figure out how happening.
this may me:
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 matches being logged hapijs.

Comments
Post a Comment