Getting Started with PDFPack

Installation

Installation uses the npm package manager. Just type the following command after installing npm.

npm install PDFPack

Creating a document

Creating a PDFPack document is quite simple. Just require the PDFPack module in your JavaScript source file and create an instance of the PDFDocument class.

const PDFDocument = require('PDFPack');
const doc = new PDFDocument;

PDFDocument instances are readable Node streams. They don't get saved anywhere automatically, but you can call the pipe method to send the output of the PDF document to another writable Node stream as it is being written. When you're done with your document, call the end method to finalize it. Here is an example showing how to pipe to a file or an HTTP response.

doc.pipe(fs.createWriteStream('/path/to/file.pdf')); // write to PDF
doc.pipe(res);                                       // HTTP response
// add stuff to PDF here using methods described below...
// finalize the PDF and end the stream
doc.end();

The write and output methods found in PDFPack before version 0.5 are now deprecated.

Using PDFPack in the browser

As of version 0.6, PDFPack can be used in the browser as well as in Node! There are two ways to use PDFPack in the browser. The first is to use Browserify, which is a Node module packager for the browser with the familiar require syntax. The second is to use a prebuilt version of PDFPack, which you can download .

Using PDFPack in the browser is exactly the same as using it in Node, except you'll want to pipe the output to a destination supported in the browser, such as a Blob. Blobs can be used to generate a URL to allow display of generated PDFs directly in the browser via an iframe, or they can be used to upload the PDF to a server, or trigger a download in the user's browser.

To get a Blob from a PDFDocument, you should pipe it to a blob-stream, which is a module that generates a Blob from any Node-style stream. The following example uses Browserify to load PDFPack and blob-stream, but if you're not using Browserify, you can load them in whatever way you'd like (e.g. script tags).

// require dependencies
const PDFDocument = require('PDFPack');
const blobStream  = require('blob-stream');
// create a document the same way as above
const doc = new PDFDocument;
// pipe the document to a blob
const stream = doc.pipe(blobStream());
// add your content to the document here, as usual
// get a blob when you're done
doc.end();
stream.on('finish', function() {
  // get a blob you can do whatever you like with
  const blob = stream.toBlob('application/pdf');
  // or get a blob URL for display in the browser
  const url = stream.toBlobURL('application/pdf');
  iframe.src = url;
});

You can see an interactive in-browser demo of PDFPack here.

Note that in order to Browserify a project using PDFPack, you need to install the brfs module with npm, which is used to load built-in font data into the package. It is listed as a devDependency in PDFPack's package.json, so it isn't installed by default for Node users. If you forget to install it, Browserify will print an error message.

Adding pages

The first page of a PDFPack document is added for you automatically when you create the document unless you provide autoFirstPage: false. Subsequent pages must be added by you. Luckily, it is quite simple!

doc.addPage()

To add some content every time a page is created, either by calling addPage() or automatically, you can use the pageAdded event.

doc.on('pageAdded', () => doc.text("Page Title"));

You can also set some options for the page, such as its size and orientation.

The layout property can be either portrait (the default) or landscape. The size property can be either an array specifying [width, height] in PDF points (72 per inch), or a string specifying a predefined size. A list of the predefined paper sizes. The default is letter.

Passing a page options object to the PDFDocument constructor will set the default paper size and layout for every page in the document, which is then overridden by individual options passed to the addPage method.

You can set the page margins in two ways. The first is by setting the margin property (singular) to a number, which applies that margin to all edges. The other way is to set the margins property (plural) to an object with top, bottom, left, and right values. The default is a 1 inch (72 point) margin on all sides.

For example:

// Add a 50 point margin on all sides
doc.addPage({
  margin: 50});
// Add different margins on each side
doc.addPage({
  margins: {
    top: 50,
    bottom: 50,
    left: 72,
    right: 72
  }
});

Switching to previous pages

PDFPack normally flushes pages to the output file immediately when a new page is created, making it impossible to jump back and add content to previous pages. This is normally not an issue, but in some circumstances it can be useful to add content to pages after the whole document, or a part of the document, has been created already. Examples include adding page numbers, or filling in other parts of information you don't have until the rest of the document has been created.

PDFPack has a bufferPages option in versions v0.7.0 and later that allows you to control when pages are flushed to the output file yourself rather than letting PDFPack handle that for you. To use it, just pass bufferPages: true as an option to the PDFDocument constructor. Then, you can call doc.switchToPage(pageNumber) to switch to a previous page (page numbers start at 0).

When you're ready to flush the buffered pages to the output file, call flushPages. This method is automatically called by doc.end(), so if you just want to buffer all pages in the document, you never need to call it. Finally, there is a bufferedPageRange method, which returns the range of pages that are currently buffered. Here is a small example that shows how you might add page numbers to a document.

// create a document, and enable bufferPages mode
let i;
let end;
const doc = new PDFDocument({
  bufferPages: true});
// add some content...
doc.addPage();
// ...
doc.addPage();
// see the range of buffered pages
const range = doc.bufferedPageRange(); // => { start: 0, count: 2 }
for (i = range.start, end = range.start + range.count, range.start <= end; i < end; i++;) {
  doc.switchToPage(i);
  doc.text(`Page ${i + 1} of ${range.count}`);
}
// manually flush pages that have been buffered
doc.flushPages();
// or, if you are at the end of the document anyway,
// doc.end() will call it for you automatically.
doc.end();

Setting document metadata

PDF documents can have various metadata associated with them, such as the title, or author of the document. You can add that information by adding it to the doc.info object, or by passing an info object into the document at creation time.

Here is a list of all of the properties you can add to the document metadata. According to the PDF spec, each property must have its first letter capitalized.

Encryption and Access Privileges

PDF specification allow you to encrypt the PDF file and require a password when opening the file, and/or set permissions of what users can do with the PDF file. PDFPack implements standard security handler in PDF version 1.3 (40-bit RC4), version 1.4 (128-bit RC4), PDF version 1.7 (128-bit AES), and PDF version 1.7 ExtensionLevel 3 (256-bit AES).

To enable encryption, provide a user password when creating the PDFDocument in options object. The PDF file will be encrypted when a user password is provided, and users will be prompted to enter the password to decrypt the file when opening it.

To set access privileges for the PDF file, you need to provide an owner password and permission settings in the option object when creating PDFDocument. By default, all operations are disallowed. You need to explicitly allow certain operations.

Following settings are allowed in permissions object:

You can specify either user password, owner password or both passwords. Behavior differs according to passwords you provides:

Note that PDF file itself cannot enforce access privileges. When file is decrypted, PDF viewer applications have full access to the file content, and it is up to viewer applications to respect permission settings.

To choose encryption method, you need to specify PDF version. PDFPack will choose best encryption method available in the PDF version you specified.

Available options includes:

When using PDF version 1.7 ExtensionLevel 3, password is truncated to 127 bytes of its UTF-8 representation. In older versions, password is truncated to 32 bytes, and only Latin-1 characters are allowed.

Adding content

Once you've created a PDFDocument instance, you can add content to the document. Check out the other sections described in this document to learn about each type of content you can add.

That's the basics! Now let's move on to PDFPack's powerful vector graphics abilities.