JavaScript and the Art of Printing PDFs

Ah, the digital age: where documents fly across the globe in seconds and ink and paper seem quaint. But sometimes, we gotta kick it old-school and print out a PDF from our web apps. As a full-stack dev who’s seen a fair share of print buttons, I’m gonna walk you through the ins and outs of printing PDFs with JavaScript. Whether you’re generating reports, invoices, or just want to offer a download for that super helpful user manual, I’ve got the code snippets to get you started.

Client-Side Printing with JavaScript

Let’s start with the basics. You’ve got a PDF URL and you want to pop open the print dialog in the user’s browser. Good news, it’s pretty straightforward:

function printPDF(url) < // This opens a new window with the PDF file const win = window.open(url, '_blank'); win.focus(); // Wait for the PDF to load and then print it win.onload = function() < win.print(); >; > 

This little snippet does the trick for most cases. But what if you’re dealing with more complex scenarios or want a more seamless experience? Buckle up, we’re going deeper.

Printing PDFs with PDF.js

When you need more control over how PDFs are handled in the browser, PDF.js is your go-to library. It’s a general-purpose, web standards-based platform for parsing and rendering PDFs, and it’s what powers the PDF viewer in Firefox.

Here’s how to use PDF.js to print a PDF:

import < getDocument >from 'pdfjs-dist/webpack'; function printPDFWithPDFjs(url) < const loadingTask = getDocument(url); loadingTask.promise.then(pdfDocument => < // Fetch the first page pdfDocument.getPage(1).then(page =>< // You'll need to create a canvas element var viewport = page.getViewport(< scale: 1.0 >); var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); canvas.height = viewport.height; canvas.width = viewport.width; // Render the page on the canvas var renderContext = < canvasContext: ctx, viewport: viewport, >; page.render(renderContext).promise.then(() => < // Convert canvas to an image blob canvas.toBlob(blob =>< // Create a new object URL for the blob var newUrl = URL.createObjectURL(blob); // Use the previous technique to print the blob const win = window.open(newUrl, '_blank'); win.onload = function() < win.print(); >; >); >); >); >).catch(function(reason) < console.error('Error: ' + reason); >); > 

With PDF.js, you’re no longer limited to just printing the first page or relying on the browser’s built-in viewer. You can render individual pages to canvas elements, manipulate them, and then trigger the print dialog.

Generating and Printing PDFs with jsPDF

Sometimes, you need to generate a PDF on the fly and then print it. That’s where jsPDF comes into play. It’s a library that allows you to create PDF documents using JavaScript.

Here’s a quick example of generating a simple PDF and then printing it:

import < jsPDF >from "jspdf"; function generateAndPrintPDF() < // Create a new instance of jsPDF const doc = new jsPDF(); // Add some content doc.text("Hello world!", 10, 10); // Output the PDF as a data URI const dataUri = doc.output('datauristring'); // Open the data URI in a new window var win = window.open(); win.document.write(' '); // Wait for the iframe to load and then print it const iframe = win.document.querySelector('iframe'); iframe.onload = function() < win.focus(); win.print(); >; > 

With jsPDF, you’re in complete control of the PDF generation. You can add text, images, shapes, and more. Then, you can either offer it as a downloadable file or print it directly from the browser.

That wraps up the first half of our journey into printing PDFs with JavaScript. We’ve covered client-side printing, using PDF.js for more control, and generating PDFs on the fly with jsPDF. Stay tuned for the second half, where we’ll dive into server-side PDF generation and more advanced client-side options. Happy printing!

Server-Side PDF Generation with Node.js

While client-side PDF generation is great for many applications, sometimes you need the power and control of server-side processing. Whether it’s for performance, privacy, or just because the client’s device isn’t up to the task, Node.js has got you covered.

Generating PDFs with Puppeteer

Puppeteer is a Node library which provides a high-level API to control Chrome or Chromium over the DevTools Protocol. It’s perfect for generating PDFs of content that’s rendered in the browser.

Here’s how to use Puppeteer to generate a PDF on the server:

const puppeteer = require('puppeteer'); async function printPDF(url) < const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto(url, < waitUntil: 'networkidle0' >); const pdf = await page.pdf(< format: 'A4' >); await browser.close(); return pdf; > // Usage: printPDF('http://example.com').then(pdf => < // Here you can write the PDF to a file, send it over the network, etc. >); 

With Puppeteer, you can take a URL (either public or within your private network), render the page in a headless browser, and then output a PDF. It’s like having a print-to-PDF feature on the server.

Creating PDFs with pdfkit

Another great option for server-side PDF generation is pdfkit, a PDF generation library for Node that makes creating complex, multi-page, printable documents easy.

Here’s a basic example of generating a PDF with pdfkit:

const PDFDocument = require('pdfkit'); const fs = require('fs'); function createPDF() < // Create a document const doc = new PDFDocument(); // Pipe its output somewhere, like to a file or HTTP response // See below for browser usage doc.pipe(fs.createWriteStream('output.pdf')); // Embed a font, set the font size, and render some text doc .font('fonts/PalatinoBold.ttf') .fontSize(25) .text('Some text with an embedded font!', 100, 100); // Add another page doc.addPage() .fontSize(25) .text('Here is some vector graphics. ', 100, 100); // Draw a triangle doc.save() .moveTo(100, 150) .lineTo(100, 250) .lineTo(200, 250) .fill("#FF3300"); // Finalize PDF file doc.end(); >createPDF(); 

In this example, pdfkit is used to create a PDF with text and graphics. The output can be piped to a file, HTTP response, or any writable stream.

Advanced Client-Side Printing Techniques

Sometimes, you need a bit more than just printing a PDF. Maybe you want to print directly from the client-side without user interaction, or you need to print part of a page or a dynamically generated document.

Silent Printing with qz-tray

For silent, client-side printing, you can use qz-tray, a cross-browser, cross-platform plugin for sending documents and raw commands to a printer.

const qz = require('qz-tray'); // Connect to the qz-tray service qz.websocket.connect().then(() => < return qz.printers.find(); // Pass the printer name >).then(printer => < var config = qz.configs.create(printer); // Create a PDF blob var pdfBlob = new Blob([/* PDF data as array goes here */], < type: 'application/pdf' >); // Send PDF to the printer return qz.print(config, [< type: 'pdf', data: pdfBlob >]); >).catch(e => < console.error(e); >); 

Using qz-tray, you can bypass the standard print dialog and directly interface with the user’s printer. This is particularly useful for kiosk or POS applications where silent printing is essential.

Printing Part of a Web Page

Sometimes, you don’t want to print a whole PDF or even a whole web page — just part of it. Here’s how you can do that with plain JavaScript:

function printElement(elem) < const printWindow = window.open('', 'PRINT', 'height=600,width=800'); printWindow.document.write('' + document.title + ''); printWindow.document.write(''); printWindow.document.write(elem.outerHTML); printWindow.document.write(''); printWindow.document.close(); // necessary for IE >= 10 printWindow.focus(); // necessary for IE >= 10 printWindow.print(); printWindow.close(); > // Usage: printElement(document.getElementById('printableArea')); 

This function opens a new window, writes the HTML of the element you want to print to the new window, and triggers the print dialog.

And there you have it, folks — a deep dive into printing PDFs with JavaScript, from client-side quick prints to server-side PDF generation, and even silent printing and partial page printing. Whether you’re building a simple web app or a complex enterprise system, these tools and techniques should cover all your printable document needs. Keep in mind that printing can be a complex topic due to the variety of user environments and browsers, but with the right approach, you can create a smooth and user-friendly print experience. Happy coding and happy printing!