0

I am using the 'html-pdf' npm package to create a byte array in a nodeJs azure function. I can log and see that the byte array is being created but when i call my function i cannot get the buffer to return. My response is a 200 and again i can see the buffer if i log it to string. For context the package takes an html string and returns a pdf .How do i set the response to return the byte array?

var pdf = require('html-pdf');

module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');
    if ((req.body && req.body.data)) {
        var html = req.body.data;
        context.log(html);
        console.log(html);
        var data = []
         pdf.create(html).toBuffer(function(err, buffer){
            data.push(buffer);
            context.res = {
                setEncoding: 'binary',
                // status: 200, /* Defaults to 200 */
                body: Buffer.concat(data)
            };
          });
    }
    else {
        context.res = {
            status: 400,
            body: "Please pass a name on the query string or in the request body"
        };
    }
};
Leonardo Wildt
  • 2,529
  • 5
  • 27
  • 56

2 Answers2

1

I could reproduce this issue, then I do some research and got a reliable answer, so I change the function a normal function(non-async) function.

Below is my test code:

var pdf = require('html-pdf');
module.exports = function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');
    const html=req.body;
    context.log(html);
    var data = []
    pdf.create(html).toBuffer(function(err, buffer){
    data.push(buffer);
    context.res = {
        setEncoding: 'binary',
        // status: 200, /* Defaults to 200 */
        body: Buffer.concat(data)
    };
    context.done();
    });
}

I use the postman to send the request, it returns a response I choose the Save to a file, then I open the file It's complete.

enter image description here

George Chen
  • 13,703
  • 2
  • 11
  • 26
0

If anyone needs to figure this out in the future you have to create a new promise from pdf.create. My code now looks like this. This doesnt work in an azure function apparently due to GDI support for phantom js

UPDATE this now works if deployed to an app service plan. Will not work in consumption plan in azure.

var pdf = require('html-pdf');


module.exports = async function (context, req) {
    context.log('JavaScript HTTP trigger function processed a request.');
    const html=req.body.data;
    var data = await returnHtmlAsPdf(html);
    var data2 = []
    data2.push(data);
    context.res = {
        setEncoding: 'binary',
        // status: 200, /* Defaults to 200 */
        body: Buffer.concat(data2)
    };
    context.done();
};

async function returnHtmlAsPdf(html) {
    return new Promise((resolve, reject) => {
        pdf.create(html).toBuffer(function(err, buffer){
            if(err){
                reject(err);
            }
            resolve(buffer);
        })
    });

}
Leonardo Wildt
  • 2,529
  • 5
  • 27
  • 56
  • is S1 app service plan sufficient for this? – MatnikR Sep 10 '21 at 12:34
  • So long as its dedicated and not consumption should be fine. – Leonardo Wildt Sep 10 '21 at 14:54
  • Thanks. One thing to remember though, which costed me few hours. If you use e.g. VS Code on Mac you need to make sure you use phantomjs-prebuild from some Windows deployment - otherwise it will not work. Deployment will fetch mac binaries and put it to azure functions windows, causing phantom.js to crash. – MatnikR Sep 10 '21 at 19:25