PDFKit для JavaScript (Node.js): полное руководство с примерами

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Введение в PDFKit

PDFKit — это мощная и гибкая библиотека для генерации PDF-документов на стороне сервера с использованием JavaScript (Node.js). Она предоставляет разработчикам полный контроль над процессом создания PDF: от простых текстовых документов до сложных многостраничных отчётов с таблицами, изображениями, графикой и интерактивными элементами. PDFKit не требует установки дополнительных зависимостей, таких как PhantomJS или Puppeteer, и работает исключительно на чистом JavaScript, что делает его идеальным выбором для высоконагруженных серверных приложений.

Зачем нужна эта библиотека? В современной веб-разработке часто возникает необходимость генерировать PDF-документы программно: счета, накладные, отчёты, сертификаты, договоры. PDFKit решает эту задачу элегантно и эффективно. В отличие от HTML-to-PDF конвертеров, которые могут быть медленными и непредсказуемыми, PDFKit даёт вам прямой доступ к PDF-модели: вы сами определяете координаты каждого элемента, управляете шрифтами, цветами и компоновкой страниц. Это особенно важно, когда требуется точное позиционирование элементов или работа с нестандартными форматами.

Библиотека активно поддерживается сообществом, имеет обширную документацию и используется в production-среде тысячами компаний по всему миру. PDFKit поддерживает все основные возможности формата PDF: встраивание шрифтов (включая кириллицу), работу с изображениями (JPEG, PNG, SVG), создание аннотаций, гиперссылок, закладок, а также шифрование документов. Благодаря модульной архитектуре и возможности потоковой записи, PDFKit отлично подходит для создания как небольших документов, так и многогигабайтных PDF-файлов.

Установка PDFKit

PDFKit распространяется через пакетный менеджер npm. Установка производится стандартной командой:

npm install pdfkit

Для работы с TypeScript может потребоваться установка дополнительных типов:

npm install pdfkit @types/pdfkit

Если вы используете Yarn:

yarn add pdfkit

После установки библиотека готова к использованию. Никаких дополнительных зависимостей или системных требований не требуется — всё работает "из коробки" на любой платформе, поддерживающей Node.js (Windows, macOS, Linux).

Быстрый старт: минимальный рабочий пример

Создайте файл hello-pdf.js и добавьте следующий код:

const PDFDocument = require('pdfkit');
const fs = require('fs');

// Создаём новый PDF-документ
const doc = new PDFDocument();

// Указываем, куда сохранить результат
doc.pipe(fs.createWriteStream('hello.pdf'));

// Добавляем текст
doc.fontSize(25)
   .text('Привет, мир!', 100, 100);

// Завершаем документ
doc.end();

console.log('PDF создан: hello.pdf');

Запустите скрипт:

node hello-pdf.js

В текущей директории появится файл hello.pdf с текстом "Привет, мир!". Этот пример демонстрирует базовый принцип работы с PDFKit: создание документа, добавление контента и сохранение результата.

Основные методы и классы PDFKit

PDFKit предоставляет богатый API для работы с PDF-документами. Рассмотрим основные методы, которые пригодятся в повседневной разработке.

1. new PDFDocument(options) — Конструктор документа

Сигнатура: new PDFDocument([options])

Описание: Создаёт новый экземпляр PDF-документа. Параметр options — объект, позволяющий задать размер страницы, поля, ориентацию, метаданные и другие настройки.

const doc = new PDFDocument({
  size: 'A4',              // Размер страницы (A4, Letter, Legal и др.)
  layout: 'portrait',      // Ориентация: 'portrait' или 'landscape'
  margins: {               // Поля страницы
    top: 50,
    bottom: 50,
    left: 50,
    right: 50
  },
  info: {                  // Метаданные документа
    Title: 'Мой документ',
    Author: 'Иван Иванов',
    Subject: 'Пример PDF',
    Keywords: 'PDFKit, пример'
  }
});

2. doc.text(text, x, y, options) — Добавление текста

Сигнатура: doc.text(text, [x], [y], [options])

Описание: Добавляет текстовый блок на страницу. Поддерживает автоматический перенос строк, выравнивание, межстрочный интервал и другие параметры форматирования.

doc.font('Helvetica')      // Шрифт
   .fontSize(14)           // Размер шрифта
   .fillColor('#333333')   // Цвет текста
   .text('Это пример текста с форматированием.', {
     width: 400,           // Ширина текстового блока
     align: 'center',      // Выравнивание: 'left', 'center', 'right', 'justify'
     lineGap: 5            // Межстрочный интервал
   });

3. doc.image(path, x, y, options) — Вставка изображения

Сигнатура: doc.image(path, [x], [y], [options])

Описание: Вставляет изображение в документ. Поддерживает форматы JPEG, PNG и SVG. Позволяет масштабировать, обрезать и позиционировать изображение.

// Вставка изображения с сохранением пропорций
doc.image('logo.png', 50, 50, {
  fit: [200, 100],         // Максимальные размеры
  align: 'center',         // Выравнивание внутри области
  valign: 'middle'
});

// Вставка с явным указанием размеров
doc.image('photo.jpg', 100, 200, {
  width: 150,
  height: 100
});

4. doc.font(bufferOrPath, family) — Установка шрифта

Сигнатура: doc.font(bufferOrPath, [family])

Описание: Загружает и устанавливает шрифт для последующего использования. Поддерживает встраивание шрифтов (включая кириллические) из файлов TTF, OTF или буферов.

// Загрузка шрифта из файла
doc.font('fonts/OpenSans-Regular.ttf')
   .fontSize(12)
   .text('Текст с кастомным шрифтом', 50, 50);

// Загрузка шрифта из буфера
const fontBuffer = fs.readFileSync('fonts/Roboto-Bold.ttf');
doc.font(fontBuffer)
   .fontSize(16)
   .text('Жирный текст', 50, 100);

5. doc.rect(x, y, width, height) — Рисование прямоугольника

Сигнатура: doc.rect(x, y, width, height)

Описание: Рисует прямоугольник. Используется в сочетании с методами .fill() (заливка) и .stroke() (обводка) для создания фигур.

// Залитый прямоугольник
doc.rect(50, 50, 200, 100)
   .fill('#FF0000');

// Прямоугольник с обводкой
doc.rect(300, 50, 200, 100)
   .stroke('#0000FF');

// Прямоугольник с заливкой и обводкой
doc.rect(50, 200, 200, 100)
   .fillAndStroke('#00FF00', '#000000');

6. doc.circle(x, y, radius) — Рисование окружности

Сигнатура: doc.circle(x, y, radius)

Описание: Рисует окружность с центром в указанной точке. Как и rect, используется с методами .fill() и .stroke().

// Залитая окружность
doc.circle(150, 150, 100)
   .fill('#FFD700');

// Окружность с обводкой
doc.circle(400, 150, 80)
   .stroke('#FF6600');

// Окружность с заливкой и обводкой
doc.circle(275, 350, 60)
   .fillAndStroke('#FF69B4', '#8B008B');

7. doc.moveTo(x, y) и doc.lineTo(x, y) — Рисование линий

Сигнатура: doc.moveTo(x, y) и doc.lineTo(x, y)

Описание: Методы для построения произвольных путей. moveTo устанавливает начальную точку, lineTo проводит линию до указанной точки. Завершается методом .stroke().

// Рисуем линию
doc.moveTo(50, 50)
   .lineTo(250, 250)
   .stroke('#000000');

// Рисуем треугольник
doc.moveTo(300, 100)
   .lineTo(400, 250)
   .lineTo(200, 250)
   .closePath()  // Замыкаем путь
   .fill('#FFA500');

8. doc.addPage(options) — Добавление новой страницы

Сигнатура: doc.addPage([options])

Описание: Добавляет новую страницу в документ. Позволяет задать индивидуальные параметры для каждой страницы (размер, ориентацию, поля).

// Первая страница (A4, портретная)
doc.text('Страница 1', 50, 50);

// Вторая страница (A3, альбомная)
doc.addPage({
  size: 'A3',
  layout: 'landscape',
  margins: { top: 30, bottom: 30, left: 30, right: 30 }
});
doc.text('Страница 2 (A3, альбомная)', 50, 50);

// Третья страница с кастомным размером
doc.addPage({
  size: [400, 600]  // Ширина 400, высота 600
});
doc.text('Страница 3 (кастомный размер)', 50, 50);

9. doc.table(table, options) — Создание таблицы (расширение)

Сигнатура: doc.table(table, [options])

Описание: Метод доступен при использовании плагина pdfkit-table. Позволяет создавать сложные таблицы с автоматическим переносом строк, объединением ячеек и стилизацией.

// Установка плагина: npm install pdfkit-table
const PDFDocument = require('pdfkit-table');

const doc = new PDFDocument();

const table = {
  headers: ['Имя', 'Возраст', 'Город'],
  rows: [
    ['Иван', '25', 'Москва'],
    ['Мария', '30', 'Санкт-Петербург'],
    ['Алексей', '28', 'Новосибирск']
  ]
};

doc.table(table, {
  prepareHeader: () => doc.font('Helvetica-Bold').fontSize(12),
  prepareRow: (row, i) => doc.font('Helvetica').fontSize(10)
});

10. doc.link(x, y, width, height, url) — Добавление гиперссылки

Сигнатура: doc.link(x, y, width, height, url)

Описание: Создаёт интерактивную область с гиперссылкой. При клике на область в PDF-ридере открывается указанный URL.

// Текст-ссылка
doc.fontSize(14)
   .fillColor('blue')
   .text('Нажмите здесь, чтобы перейти на сайт', 50, 50);

// Создаём область ссылки поверх текста
doc.link(50, 50, 300, 20, 'https://example.com');

// Ссылка на внутреннюю страницу документа
doc.link(50, 100, 200, 20, '#page=3');

Реальный практический пример: генерация счёта-фактуры

Рассмотрим полный пример создания счёта-фактуры для интернет-магазина. Документ будет содержать логотип компании, реквизиты, таблицу товаров и итоговую сумму.

const PDFDocument = require('pdfkit');
const fs = require('fs');

// Создаём документ
const doc = new PDFDocument({
  size: 'A4',
  margins: { top: 50, bottom: 50, left: 50, right: 50 },
  info: {
    Title: 'Счёт-фактура №12345',
    Author: 'ООО "Рога и Копыта"',
    Subject: 'Счёт на оплату'
  }
});

// Поток для записи
const stream = fs.createWriteStream('invoice.pdf');
doc.pipe(stream);

// --- Шапка документа ---
// Логотип (если файл существует)
if (fs.existsSync('logo.png')) {
  doc.image('logo.png', 50, 45, { width: 80 });
}

// Название компании
doc.font('Helvetica-Bold')
   .fontSize(20)
   .text('ООО "Рога и Копыта"', 150, 50);

// Реквизиты компании
doc.font('Helvetica')
   .fontSize(10)
   .text('ИНН: 1234567890', 150, 80)
   .text('КПП: 123456789', 150, 95)
   .text('Расчётный счёт: 40702810123456789012', 150, 110)
   .text('БИК: 044525225', 150, 125);                    

Рекомендаций