Convert HTML or URL to PDF in Node using Rotativa.io API

date Oct 14, 2016

Creating PDF files in Node.js using Rotativa.io is simple. You can either pass the service a URL or a HTML document. Making the call, using the request npm package, is this simple:

var request = require('request');
var fs = require('fs');

request({
    url: 'https://eunorth.rotativahq.com',
    method: "POST",
    json: { htmlUrl: "http://www.vodafone.it" },
    followAllRedirects: true,
    encoding: null,
    headers: { "X-ApiKey": "<YOUR_APIKEY>" }
  },
  function (error, response, body) {
    if (!error && response.statusCode == 200) {
      fs.writeFile('testdoc.pdf', body);
    }
  }
);

The followAllRedirects option set to true is required because the response will redirect to a temporary file on cloud storage. This file is available for 2 minutes.

Setting encoding to null makes the body parameter of the response a buffer that you can stream back to a web user. The sample simply writes a PDF file to disk.

JSON payload can contain a URL or a HTML string, in the htmlUrl and html properties.

You should add a header with the ApiKey you can get on the preferences page. You can sign up for a free account here.

A template engine can be used to build the HTML string to pass to Rotativa.io. The following code uses Pug (formerly Jade) as a template engine.

var request = require('request');
var fs = require('fs');
var pug = require('pug');

var htmlString = pug.renderFile('index.pug', {
  name: 'Giorgio'
});

request({
    url: 'https://eunorth.rotativahq.com',
    method: "POST",
    json: { html: htmlString },
    followAllRedirects: true,
    encoding: null,
    headers: { "X-ApiKey": "<YOUR_APIKEY>" }
  },
  function (error, response, body) {
    if (!error && response.statusCode == 200) {
      fs.writeFile('testdoc.pdf', body);
    }
  }
);

You might want to consider managing yourself the temporary link to the PDF. If you add the returnLink option set to true, it will return a json containing the URL of the PDF file.

var request = require('request');
var fs = require('fs');
var pug = require('pug');

var htmlString = pug.renderFile('index.pug', {
  name: 'Giorgio'
});

request({
    url: 'https://eunorth.rotativahq.com',
    method: "POST",
    json: {
      html: htmlString,
      filename: 'mytest.pdf',
      returnLink: true
    },
    followAllRedirects: true,
    encoding: null,
    headers: { "X-ApiKey": "<YOUR_APIKEY>" }
  },
  function (error, response, body) {
    if (!error && response.statusCode == 200) {
      console.log(body);
    }
  }
);

The filename option sets the name of the file that will be downloaded from the URL. Resulting JSON is:

{ 
  "pdfUrl": "https://rhqeuno2.blob.core.windows.net/temppdf/983ace5d51c346cbae5c9dc7cfa4673d.pdf?sv=2015-04-05&sr=b&si=twominutepolicy&sig=yCVpSDWteeU6Rc7%2Fx7rwI311atP76j2zwiExwmb0UD8%3D" 
}

Redirecting the user yourself will spare a roundtrip and this could shorten download times.

The following code is a sample express route that redirects to a PDF generated by RotativaHQ:

app.get('/', function (req, res) {
  request({
      url: 'https://eunorth.rotativahq.com',
      method: "POST",
      json: { htmlUrl: "http://www.vodafone.it", returnLink: true },
      followAllRedirects: true,
      encoding: null,
      headers: { "X-ApiKey": "<YOUR_APIKEY>" }
    },
    function (error, response, body) {
      if (!error && response.statusCode == 200) {
        res.redirect(body.pdfUrl);
      }
    }
  );
});

In this way the PDF doc doesn’t have to be transferred first from Rotativa.io endpoint to your server and then from your server to the user. The user directly downloads the file from Rotativa.io (as a temporary file with a 2 minutes lifetime).

The complete list of options for the request JSON:

{
  "htmlUrl": "",
  "html": ""
  "filename": "",
  "returnLink": true,
  "pageMargins": {
    "bottom": null,
    "left": null,
    "right": null,
    "top": null
  },
  "pageSize": null,
  "pageWidth": null,
  "pageHeight": null,
  "pageOrientation": "portrait",
  "isJavaScriptDisabled": false,
  "isLowQuality": false,
  "isBackgroundDisabled": false,
  "minimumFontSize": null,
  "copies": null,
  "isGrayScale": false,
  "customSwitches": null
}

Those parameters will be converted to wkhtmltopdf parameters. If any are missing, you can manually add them in the customSwitches property.