Files
2026-07-12 10:17:17 -04:00

2.4 KiB

Exporting PDF Pages as PNG Images

When you need to export every page of a jsPDF document as individual PNG images (e.g., for sharing in chat, embedding in emails, or image-only workflows):

Installation

npm install pdfjs-dist

Worker Setup (main.tsx or entry point)

import * as pdfjsLib from 'pdfjs-dist';

pdfjsLib.GlobalWorkerOptions.workerSrc = new URL(
  'pdfjs-dist/build/pdf.worker.min.mjs',
  import.meta.url,
).toString();

Implementation Pattern

The function accepts EITHER a jsPDF instance OR a Blob (from a function that returns doc.output('blob')):

export async function downloadPdfAsImages(
  pdfInput: jsPDF | Blob,
  customerName: string,
): Promise<void> {
  // 1. Get raw PDF bytes
  let arrayBuffer: ArrayBuffer;
  if (pdfInput instanceof Blob) {
    arrayBuffer = await pdfInput.arrayBuffer();
  } else {
    arrayBuffer = pdfInput.output('arraybuffer');
  }

  // 2. Load into pdfjs
  const pdf = await pdfjsLib.getDocument({ data: arrayBuffer }).promise;

  // 3. Render each page to canvas, then trigger download
  for (let pageNum = 1; pageNum <= pdf.numPages; pageNum++) {
    const page = await pdf.getPage(pageNum);
    const viewport = page.getViewport({ scale: 2 }); // 2x = Retina

    const canvas = document.createElement('canvas');
    canvas.width = viewport.width;
    canvas.height = viewport.height;
    const ctx = canvas.getContext('2d')!;

    await page.render({ canvasContext: ctx, viewport }).promise;

    const blob = await new Promise<Blob>((resolve) => {
      canvas.toBlob((b) => resolve(b!), 'image/png');
    });

    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `${customerName.replace(/\s+/g, '_')}_Page${pageNum}.png`;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
    page.cleanup();
  }
}

Key Details

  • Scale: getViewport({ scale: 2 }) = 144 DPI. Use 1 for smaller files, 3-4 for print quality.
  • Blob path: If you have a function that already builds the PDF and returns doc.output('blob'), pass the blob directly — you don't need access to the jsPDF instance.
  • Browser download: Each page triggers its own download. Browsers batch them into the download bar.
  • Memory: URL.revokeObjectURL() and page.cleanup() prevent leaks with many pages.
  • Dependency: pdfjs-dist adds ~2MB to the bundle (worker + core).