Введение в 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); Также в библиотеке
Очереди задач в Rust: Обзор библиотек для асинхронной обработки
Swagger/OpenAPI генерация для C++: обзор инструментов и библиотек
Планировщик задач Java: Quartz Scheduler – полное руководство
Генератор QR-кодов на Rust: библиотека qr_code