Have you ever tried to create PDFs with complicated and fancy charts using PDFKit? such a **** task isn't ?. We know about the awesome PDFKIT for node.js, PDFKit is a PDF document generation library for Node and the browser that makes creating complex, multi-page, printable documents easy. The following code should generate a simple PDF document with some text:
var PDFDocument, doc;
var fs = require("fs");
PDFDocument = require('pdfkit');
doc = new PDFDocument;
doc.pipe(fs.createWriteStream('output.pdf'));
doc.fontSize(25).text('Some text with an embedded font!', 100, 100);
doc.addPage().fontSize(25).text('Here is some vector graphics...', 100, 100);
doc.save().moveTo(100, 150).lineTo(100, 250).lineTo(200, 250).fill("#FF3300");
doc.scale(0.6).translate(470, -380).path('M 250,75 L 323,301 131,161 369,161 177,301 z').fill('red', 'even-odd').restore();
doc.addPage().fillColor("blue").text('Here is a link!', 100, 100).underline(100, 100, 160, 27, {
color: "#0000FF"
}).link(100, 100, 160, 27, 'http://google.com/');
doc.end();
Well, that should create the output.pdf
file in the path where you execute the script. Functional, however, i wouldn't want to draw complicated charts using that code, hell no.
An alternative to server-side generated charts, are the generation of charts with Javascript (client-side). There are a lot of Javascript libraries that allow to create fancy charts and you can retrieve its SVG (or an base64 image) and return it to the server to include them as an image in your PDF. Sounds good and functional, however there's a disadvantage with this solution. The SVG will change and will cause problems with the dimensions later in your PDF according to the resolution of the monitor of your user or the dimensions of the browser window.
Some web apps, as a solution, will generate an html view as response into the browser(which will render your fancy charts) and the user will need to use (and know how) the Browser to save (or print) the content as PDF. However, as an user, you may just want to download a PDF with a single button, choose where you want to save it and that's all.
Problems everywhere, but that's where wkhtmltopdf
comes in handy, as you'll be able to write css,html and javascript in the same way you do in a website (with some and minimal limitations obviously) and your PDF will look awesome.
In this article you'll learn how to create a PDF using wkhtmltopdf in your Node.js project.
Requirements
You'll need wkhtmltopdf
available in your system and accesible in the command prompt. wkhtmltopdf is a command line tool to render HTML into PDF and various image formats using the Qt WebKit rendering engine. These run entirely "headless" and do not require a display or display service.
- Windows: you can download an installer for each architecture (x86 and x64) in the installation area. Although you can change the path of the wkhtmltopdf executable later in the config.yml file, is recommendable to have
wkhtmltopdf
accesible as an environment variable on your system (if you don't want to create an environment variable for wkhtmltopdf, then you can provide the entire path to the executable later). You can read how to create environment variables in windows in this article. - Debian/Ubuntu: You can install the distribution from wkhtmltopdf directly in the console using the following command :
sudo apt-get install wkhtmltopdf
Once you are sure that you have wkhtmltopdf installed on your system, proceed with the usage in Node.js
Implementation
To handle wkhtmltopdf from Node.js, we need to rely on a third party module. The wkhtmltopdf module provides an useful wrapper of the command line instructions for wkhtmltopdf to generate PDFs from Node.js, to install this module execute the following command in the terminal:
npm install wkhtmltopdf
After the installation, you'll be able to require the wkhtmltopdf module using require('wkhtmltopdf')
.
Be sure the wkhtmltopdf
command line tool is in your PATH when you're done installing. If you don't want to do this for some reason, you can change the require('wkhtmltopdf').command
property to the path to the wkhtmltopdf
command line tool:
var wkhtmltopdf = require('wkhtmltopdf');
// If you don't have wkhtmltopdf in the PATH, then provide
// the path to the executable (in this case for windows would be):
wkhtmltopdf.command = "C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe";
And then you'll be able to work properly with wkhtmltopdf in Node.js.
Creating a PDF from a website
Provide a web URL (with protocol http or https) as first parameter to render a website as a PDF and provide the output path:
var wkhtmltopdf = require('wkhtmltopdf');
wkhtmltopdf('http://ourcodeworld.com', {
output: 'ourcodeworld.pdf',
pageSize: 'letter'
});
Creating a PDF from a html file
To create a PDF from the content of a html file, provide the HTML code retrieven from the file using the filesystem.readFileSync
method:
var wkhtmltopdf = require('wkhtmltopdf');
var fs = require("fs");
wkhtmltopdf(fs.readFileSync("index.html", "utf8"), {
output: 'demo.pdf',
pageSize: 'letter'
});
In this example, the html file will be index.html
and it has the following content:
<!DOCTYPE>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<h1>Hello World !</h1>
<p>This is my awesome first PDF generated using WKHTMLTOPDF with Node.js</p>
<p>UTF-8 Test : κσμε</p>
<p>Image : </p><br>
<img height="200" src="http://ourcodeworld.com/resources/img/ocw-empty.png"/>
<p>SVG Example : </p><br>
<div>
<!-- Do not forget to give width and height to your svg
use PLAIN SVG directly (<svg>content</svg>)
Tiger SVG EXAMPLE : https://upload.wikimedia.org/wikipedia/commons/f/fd/Ghostscript_Tiger.svg
-->
<img src="https://upload.wikimedia.org/wikipedia/commons/f/fd/Ghostscript_Tiger.svg" width="144" height="144"/>
</div>
<p>Canvas Example with Javascript: </p><br>
<div>
<canvas id="myCanvas" width="300" height="200"/>
</div>
<hr>
<span id="dinamic-content"></span>
<script>
document.getElementById("dinamic-content").innerHTML = 'This string has been appended using javascript';
// Draw circle on canvas
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(100,75,50,0,2*Math.PI);
ctx.stroke();
</script>
</body>
</html>
And the execution of the node code should generate a demo.pdf
file and it will look like:
Create PDF from html string
In the same way you do to render a PDF from a HTML file, just provide the HTML string as first parameter:
var wkhtmltopdf = require('wkhtmltopdf');
var htmlContent = "<h1>Test</h1><p>Hello world</p>";
wkhtmltopdf(htmlContent, {
output: 'demo.pdf',
pageSize: 'letter'
});
Note: in case you want to return a PDF file as a response, because you're using Node.js with an http server, you can simply create the file and return the file as response.
Final notes
- The node.js wkhtmltopdf allows you to add options in the same way you do with the command line, instead you need to provide them as a property in the object of the second parameter (
--page-size="letter"
would be equivalent in Javascript topageSize:"letter"
). Read all the available options of wkhtmltopdf here. - Read more about the wkhtmltopdf module for Node.js in the official repository here.
- Read more about the wkhtmltopdf library in the official website here.
Happy coding !