P.E. Joëssel P.E. Joëssel - 2 days ago 4
Node.js Question

Node (Express) - Send a pdf with express via an api

I have an api that generate invoice for each payment I have on my website. In the other side, i have a server that manage the client. I need to fetch the pdf when client ask for it.

I am using node/express and axios to manage http call.

I managed to send the pdf from the api with the following code:

function retrieveOneInvoice(req, res, next) {
Order
.findOne({_id: req.params.id, user: req.user.id})
.exec((err, order) => {
if(err) {

} else if (!order) {
res.status(404).json({success: false, message: 'Order not found!'});
} else {
const filename = order.invoice.path;
let filepath = path.join(__dirname, '../../../invoices' ,filename);

fs.readFile(filepath, function (err, data){
res.contentType("application/pdf");
res.end(data, 'binary');
});
}
});
}


That part work fine and I can fetch and save a pdf. Furthermore, if I print the data, i got a buffer that look like this:
<Buffer 25 50 44 46 2d 31 2e 34 0a 31 20 30 20 6f 62 6a 0a 3c 3c 0a 2f 54 69 74 6c 65 20 28 fe ff 29 0a 2f 43 72 65 61 74 6f 72 20 28 fe ff 29 0a 2f 50 72 6f ... >


On my client, I fetch the data with axios:

function retrieveInvoice(Config) {
return function(orderId, done) {
axios({
url: `${Config.apiUrl}/invoices/${orderId}`,
method: 'get'
}).then(
(res) => { return done(null, res.data) },
(err) => { return done(err) }
)
}
}


And finally I try to send it to the client by calling the previous function:

Api.retrieveInvoice(orderId, (err, data) => {
if(err) {

} else {
res.contentType("application/pdf");
res.end(new Buffer(data, 'binary'), 'binary');
}
});


And that is where I got my issue. I always receive blank pages. I have tried with and without the buffer, like this :

res.contentType("application/pdf");
res.end(data, 'binary');


And without the 'binary' parameter. If I log the data in both the api and my client, i got the exact same buffer and binary. As I am sending them to the client the exact same way i just can't understand where could be my mistake.

I wish I gaved you enough information to help me and i anything is missing I will add everything that could help potential helper.

Thank you for your help.

Answer

Have you tried this?

Your axios request:

axios({
    url: `${Config.apiUrl}/invoices/${orderId}`,
    method: 'get',
    responseType: 'stream'
}).then(
    ...
)

and your callback:

Api.retrieveInvoice(orderId, (err, data) => {
    if (err) {
        // handle error
    } else {
        res.contentType("application/pdf");
        data.pipe(res);
    }
});

You can find documentation on this here.

The default responseType is 'json', so changing this should solve the issue.