Hapi: Excel binary data in reply

Created on 28 Jul 2015  路  8Comments  路  Source: hapijs/hapi

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

non issue

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()

                reply(xlsx)
                    .type('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
                    .header('Content-Disposition', 'attachment; filename="'+ filename +'.xlsx"')
                    .header('Content-Length', xlsx.length);

hope this helps.

All 8 comments

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')?

@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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

arb picture arb  路  4Comments

shamsher31 picture shamsher31  路  5Comments

foobar1123 picture foobar1123  路  3Comments

mateeyow picture mateeyow  路  5Comments

andkazakov picture andkazakov  路  5Comments