Hello folks,
I've been trying to create an endpoint that returns an excel or a json based on the incoming request accept header. I've been struggling quite a bit to generate the excel from my object and return it (I used the json2xls module (https://github.com/rikkertkoppes/json2xls) to generate the data).
I simply access my endpoint through chrome: http://localhost:3000/excel
Here is a snippet of the code:
'use strict';
var Hapi = require('hapi');
var json2xls = require('json2xls');
var server = new Hapi.Server();
server.connection({port:3000});
server.route({
method : 'GET',
path : '/excel',
handler: getExcel
});
server.start(function () {
console.log('server started!');
});
function getExcel(request, reply) {
var jsonObject = {
a: 1,
b: 'stuff',
c: new Date()
};
var xls = json2xls(jsonObject);
reply(xls)
.bytes(xls.length)
.type('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
.header('content-disposition', 'attachment; filename=stuff.xlsx;');
}
In this case, the endpoint retrieves a file that is corrupted and I cannot open it.
I also tried to use a Buffer in the reply with the same result:
var xls = json2xls(jsonObject);
var buf = new Buffer(xls);
var res = reply(buf)
.bytes(buf.length)
.type('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
.header('content-disposition', 'attachment; filename=stuff.xlsx;');
Last but not least, if I write the content to disk and retrieve it. It works properly:
var xls = json2xls(jsonObject);
fs.writeFileSync('stuff.xlsx', xls, 'binary');
reply.file('stuff.xlsx');
Any help will be greatly appreciated.
Cheers,
Max
We do similar in one of our apps with no issue. Our snippet differs in setting the content-length header vs reply.bytes()
reply(xlsx)
.type('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
.header('Content-Disposition', 'attachment; filename="'+ filename +'.xlsx"')
.header('Content-Length', xlsx.length);
hope this helps.
Interesting... I still have a corrupted xlsx as an output here... @spanditcaa What is the type of your xlsx object? (string? binary?) And how do you generate It?
To me, it seems that the problem comes from the binary format...
@maxhedouin Edit: Does it help if you write reply(xls).bytes(Buffer.byteLength(xls)), or var buf = new Buffer(xls, 'binary')?
binary, made with https://www.npmjs.com/package/xlsx-style
@kitcambridge nope.
:disappointed: Sorry about that; I thought it might be an issue with encoding the binary string into a buffer.
You forgot to tell hapi to use the 'binary' string encoding by calling .encoding('binary') on the response. It defaults to 'utf8'.
Thanks @kanongil. I couldn't find that in the hapijs docs.
Most helpful comment
We do similar in one of our apps with no issue. Our snippet differs in setting the content-length header vs reply.bytes()
hope this helps.