Введение
Формат PDF является одним из самых распространенных форматов документов для передачи информации. В динамических веб-приложениях вам может понадобиться экспортировать данные в документ, и PDF обычно является популярным вариантом. В этой статье мы рассмотрим, как генерировать PDF-файлы в NodeJS с помощью NPM-пакета pdfkit.
PDFKit – это JavaScript библиотека генерации PDF для Node.js, которая обеспечивает простой способ создания многостраничных, пригодных для печати PDF-документов.
Начало работы с PDFKit
Давайте создадим каталог проекта, перейдем в него по cd и инициализируем проект Node с настройками по умолчанию:
$ mkdir pdfkit-project $ cd pdfkit-project $ npm init -y
Затем установим pdfkit:
$ npm install pdfkit
Чтобы использовать модуль в проекте, мы импортируем его с помощью require():
const PDFDocument = require('pdfkit');Создание PDF-документа с помощью PDFKit
Чтобы создать PDF-документ, нам потребуется импортировать модуль fs (файловая система). Мы передадим содержимое нашего PDF-файла в записываемый поток fs, чтобы сохранить его. Давайте рассмотрим, как это сделать:
const PDFDocument = require('pdfkit');
const fs = require('fs');
let pdfDoc = new PDFDocument;
pdfDoc.pipe(fs.createWriteStream('SampleDocument.pdf'));
pdfDoc.text("My Sample PDF Document");
pdfDoc.end();Сначала мы импортируем необходимые модули, после чего инстанцируем PDFDocument. Этот экземпляр представляет собой поток для чтения. Мы будем передавать этот поток в поток для записи, чтобы сохранить файл.
Если вы не знаете, как работают потоки, ознакомьтесь с нашим “Введением в потоки Node.js”.
Мы используем функцию pipe(), чтобы сделать это и сохранить полученный SampleDocument.pdf в наш корневой каталог. После создания мы можем добавить в него содержимое с помощью функции text. Конечно, в конце мы захотим завершить (end()) поток.
Когда мы запустим код, в корневой папке нашего проекта будет создан PDF-файл с именем SampleDocument.pdf:
$ node index.js
Примечание: Прежде чем пытаться перезаписать существующий PDF-файл, он должен быть свободен. То есть все окна с PDF-файлом должны быть закрыты, иначе программа выдаст ошибку.
Форматирование текста в PDF-файле
Конечно, pdfkit позволяет нам делать гораздо больше, чем просто добавлять неформатированный текст в документ. Давайте рассмотрим некоторые из его возможностей.
Позиционирование текста
По умолчанию модуль pdfkit отслеживает, где текст должен быть добавлен в документ, по сути, печатая каждый вызов функции text() в новой строке.
Вы можете изменить место печати текста в пределах текущей страницы, добавив в качестве аргументов к функции text() координаты x и y того места, где вы хотите разместить текст.
Например:
pdfDoc.text("Text positioned at (200,200)", 200, 200);Это полезно, поскольку позволяет точно настроить расположение текста, тем более что документы PDF имеют универсальный вид независимо от того, на какой машине/ОС они открыты. Это также позволяет, например, печатать текст поверх другого текста:
const PDFDocument = require('pdfkit');
const fs = require('fs');
var pdfDoc = new PDFDocument;
pdfDoc.pipe(fs.createWriteStream('SampleDocument.pdf'));
pdfDoc.text("From Mon-Sat we will have a 10% discount on selected items!", 150, 150);
pdfDoc
.fillColor('red')
.fontSize(17)
.text("20%", 305, 150);
pdfDoc.end();Запуск этого кода даст нам:
Перенос и выравнивание текста
Модуль pdfkit автоматически переносит строки так, чтобы они помещались между полями или по заданной ширине (при написании текста в колонках). Другими словами, опция lineBreak по умолчанию имеет значение true. Вы можете изменить его на false при вызове функции text():
pdfDoc.text("very long text ".repeat(20), { lineBreak : false });Новые страницы также добавляются автоматически по мере необходимости, то есть как только содержимое, которое вы хотите добавить, не помещается на текущей странице целиком. Однако вы также можете перейти на следующую страницу до заполнения предыдущей, просто вызвав:
pdfDoc.addPage();
Что касается выравнивания, pdfkit предоставляет нам обычные варианты – left (по умолчанию), right, center и justify. Обратите внимание, что установка определенного выравнивания при значении параметра lineBreak false не сработает, даже если текст поместится в строку.
Как и lineBreak, параметр align задается путем передачи функции text() объекта, содержащего пары ключ-значение. Давайте рассмотрим несколько примеров выравнивания:
const PDFDocument = require('pdfkit');
const fs = require('fs');
var pdfDoc = new PDFDocument;
pdfDoc.pipe(fs.createWriteStream('text_alignment.pdf'));
pdfDoc.text("This text is left aligned", { align: 'left'})
pdfDoc.text("This text is at the center", { align: 'center'})
pdfDoc.text("This text is right aligned", { align: 'right'})
pdfDoc.text("This text needs to be slightly longer so that we can see that justification actually works as intended", { align: 'justify'})
pdfDoc.end();Запуск кода выше даст нам PDF, который выглядит так:
Стилизация текста
Модуль pdfkit также предоставляет опции, которые можно использовать для стилизации текста в ваших PDF-документах. Мы рассмотрим некоторые из наиболее важных опций стилизации, полный список опций можно найти в Руководстве по PDFKit.
Мы можем передавать различные опции как пары ключ-значение в функцию text(), а также подключать несколько других функций до вызова text().
Очень важно отметить, что цепочки функций, такие как fillColor() (а затем font(), fontSize() и т.д.), будут влиять на весь текст после этого вызова:
const PDFDocument = require('pdfkit');
const fs = require('fs');
var pdfDoc = new PDFDocument;
pdfDoc.pipe(fs.createWriteStream('text_styling.pdf'));
pdfDoc
.fillColor('blue')
.text("This is a link", { link: 'https://pdfkit.org/docs/guide.pdf', underline: true });
pdfDoc
.fillColor('black')
.text("This text is underlined", { underline: true });
pdfDoc.text("This text is italicized", { oblique: true });
pdfDoc.text("This text is striked-through", { strike: true });
pdfDoc.end();Запуск этого кода будет генерировать файл PDF со следующим содержимым:
Изменение стилей в середине абзаца немного сложнее, поскольку цепочка из нескольких функций text() по умолчанию добавляет новую строку после каждой. Мы можем избежать этого, установив параметр lineBreak первого вызова text() в false:
const PDFDocument = require('pdfkit');
const fs = require('fs');
var pdfDoc = new PDFDocument;
pdfDoc.pipe(fs.createWriteStream('text_styling2.pdf'));
pdfDoc
.fillColor('blue')
.text("This text is blue and italicized", {oblique : true, lineBreak : false})
.fillColor('red')
.text(" This text is red");
pdfDoc.end();Что даст нам желаемый результат:
Создание списков
Чтобы добавить список элементов в PDF-документ, в экземпляре PDFDocument есть функция list(), которая принимает массив строковых элементов (или вложенные массивы строк) и отображает их в виде маркированного списка:
const PDFDocument = require('pdfkit');
const fs = require('fs');
let pdfDoc = new PDFDocument;
pdfDoc.pipe(fs.createWriteStream('lists.pdf'));
let myArrayOfItems = ['Item 1', 'Item 2', 'Item 3', 'Item 4'];
pdfDoc.list(myArrayOfItems);
// Move down a bit to provide space between lists
pdfDoc.moveDown(0.5);
let innerList = ['Nested Item 1', 'Nested Item 2'];
let nestedArrayOfItems = ['Example of a nested list', innerList];
pdfDoc.list(nestedArrayOfItems);
pdfDoc.end();Что дает нам:
Шрифты
PDFKit поставляется с 14 стандартными шрифтами, которые можно использовать в PDF-документах. Любой из этих шрифтов может быть передан в функцию font() класса PDFDocument и соединен с text():
pdfDoc.font('Times-Roman').text('A text in Times Roman')Вы также можете добавить дополнительные шрифты, передав путь к файлу шрифта в качестве аргумента функции font(), а также имя конкретного шрифта, который вам нужен, если файл содержит коллекцию шрифтов. Кроме того, вы можете дать новому шрифту имя, чтобы к нему можно было обращаться по этому имени, а не по пути к файлу:
pdfDoc.registerFont('Name of the font', '/file_path', 'specific_font_name_in_case_of_a_collection')Вызовы функции font() можно объединять с другими функциями, как в примере с fillColor().
Вы также можете установить размер шрифта с помощью функции fontSize(). Давайте рассмотрим несколько примеров:
const PDFDocument = require('pdfkit');
const fs = require('fs');
let pdfDoc = new PDFDocument;
pdfDoc.pipe(fs.createWriteStream('fonts.pdf'));
pdfDoc.font('ZapfDingbats').text('This is a symbolic font.');
pdfDoc.font('Times-Roman').fontSize(25).fillColor('blue').text('You can set a color for any font');
pdfDoc.font('Courier').fontSize(5).fillColor('black').text('Some text to demonstrate.');
pdfDoc.end();Запуск даст нам следующий PDF в качестве вывода:
Добавление изображений
Еще одна распространенная вещь, которую вы можете захотеть добавить в PDF-файлы, – это изображения. Вы можете вызвать функцию image() для экземпляра документа и передать путь или URI изображения, которое вы хотите включить.
Вы также можете задать такие параметры, как ширина (width), высота (height), горизонтальное (align) и вертикальное выравнивание (valign) изображения, передав в качестве аргумента функции image() объект, содержащий пары ключ-значение. По умолчанию изображения загружаются в исходном размере.
Если вы зададите ширину и высоту – изображение будет растянуто, чтобы вписаться в указанные параметры. Если один из них опущен, изображение масштабируется пропорционально заданному параметру:
const PDFDocument = require('pdfkit');
const fs = require('fs');
let pdfDoc = new PDFDocument;
pdfDoc.pipe(fs.createWriteStream('images.pdf'));
pdfDoc.text('By default, the image is loaded in its full size:')
pdfDoc.image('raspberries.jpg');
pdfDoc.moveDown(0.5)
pdfDoc.text('Scaled to fit width and height')
pdfDoc.image('raspberries.jpg', {width: 150, height: 150});
pdfDoc.moveDown(0.5)
pdfDoc.text('Scaled to fit width')
pdfDoc.image('raspberries.jpg', {width: 150});
pdfDoc.end();Запуск этого кода даст нам:
Вы также можете масштабировать изображение, задав коэффициент масштабирования. Кроме того, вы можете задать массив fit или cover, при этом изображение будет масштабировано так, чтобы оно либо поместилось в указанный прямоугольник, либо покрыло его, соответственно. Если вы задаете массив fit или cover, вы также можете установить горизонтальное выравнивание (align) и вертикальное выравнивание (valign):
const PDFDocument = require('pdfkit');
const fs = require('fs');
let pdfDoc = new PDFDocument;
pdfDoc.pipe(fs.createWriteStream('images.pdf'));
pdfDoc.text('Scaled by a factor, keeps the original proportions:')
pdfDoc.image('raspberries.jpg', {scale: 0.75});
pdfDoc.moveDown(0.5)
pdfDoc.text('Fit with horizontal alignment:')
pdfDoc.image('raspberries.jpg', {fit: [400, 150], align: 'center'});
pdfDoc.end();Это даст нам:
Заключение
В этой статье мы рассмотрели, как генерировать PDF-файлы в Node.js с помощью PDFKit. Мы рассмотрели некоторые из доступных вариантов форматирования текста и добавления изображений в наши файлы. Библиотека имеет обширную документацию, которая охватывает много других вопросов по созданию PDF-файлов в приложениях Node.js.
Оригинал: “https://stackabuse.com/generating-pdf-files-in-node-js-with-pdfkit/”