Генерация PDF в Rust: обзор библиотек и инструментов
Rust — современный системный язык программирования, который всё чаще используется для создания высокопроизводительных серверных приложений, в том числе для генерации документов. В этой статье мы рассмотрим основные библиотеки для создания PDF-файлов на Rust, их возможности, примеры использования и рекомендации по выбору.
Основные библиотеки для работы с PDF в Rust
Экосистема Rust предлагает несколько зрелых решений для генерации PDF. Рассмотрим наиболее популярные:
- printpdf — низкоуровневая библиотека с поддержкой векторной графики, изображений и шрифтов.
- genpdf — высокоуровневая библиотека для создания документов с простым API.
- pdf_writer — быстрый и безопасный генератор PDF с минимальными зависимостями.
- wkhtmltopdf — обёртка над утилитой wkhtmltopdf для конвертации HTML в PDF.
Библиотека printpdf
printpdf — одна из самых популярных библиотек для генерации PDF в Rust. Она предоставляет полный контроль над содержимым документа: текст, линии, прямоугольники, изображения и встроенные шрифты.
Установка
[dependencies]
printpdf = "0.7"
Пример: создание простого PDF с текстом
use printpdf::*;
use std::fs::File;
use std::io::BufWriter;
fn main() {
// Создаём документ формата A4
let (doc, page1, layer1) = PdfDocument::new(
"Пример документа",
Mm(210.0),
Mm(297.0),
"Layer 1"
);
// Получаем текущий шрифт (встроенный)
let font = doc.add_builtin_font(BuiltinFont::Helvetica).unwrap();
// Рисуем текст
let current_layer = doc.get_page(page1).get_layer(layer1);
current_layer.use_text(
"Привет, мир PDF из Rust!",
24.0,
Mm(20.0),
Mm(270.0),
&font
);
// Сохраняем в файл
let file = File::create("example.pdf").unwrap();
let writer = BufWriter::new(file);
doc.save(&mut std::io::BufWriter::new(writer)).unwrap();
}
Библиотека genpdf
genpdf предоставляет более высокоуровневый API, напоминающий работу с текстовыми процессорами. Поддерживает абзацы, таблицы, заголовки и автоматический перенос строк.
Установка
[dependencies]
genpdf = "0.2"
Пример: создание документа с заголовком и таблицей
use genpdf::{Document, SimplePageSettings};
use genpdf::elements::{Paragraph, Table, TableLayout};
use genpdf::fonts::FontFamily;
fn main() -> Result<(), Box> {
// Загружаем шрифт (например, DejaVu Sans)
let font_family = FontFamily::from_files(
"/usr/share/fonts/truetype/dejavu/",
"DejaVuSans",
None
)?;
// Создаём документ
let mut doc = Document::new(font_family, SimplePageSettings::a4());
// Добавляем заголовок
doc.push(Paragraph::new("Отчёт о продажах").aligned(genpdf::Alignment::Center));
// Создаём таблицу
let mut table = Table::new(TableLayout::new(vec![2, 3, 2]));
table.row()
.element(Paragraph::new("Товар"))
.element(Paragraph::new("Количество"))
.element(Paragraph::new("Цена"));
table.row()
.element(Paragraph::new("Ноутбук"))
.element(Paragraph::new("10"))
.element(Paragraph::new("50 000 руб."));
table.row()
.element(Paragraph::new("Мышь"))
.element(Paragraph::new("50"))
.element(Paragraph::new("1 500 руб."));
doc.push(table);
// Сохраняем
doc.render_to_file("report.pdf")?;
Ok(())
}
Библиотека pdf_writer
pdf_writer — минималистичная и быстрая библиотека, ориентированная на низкоуровневую работу с PDF-структурами. Идеальна для случаев, когда нужно генерировать PDF с минимальными накладными расходами.
Пример: создание пустой страницы
use pdf_writer::{PdfWriter, Writer, Rect};
fn main() {
let mut writer = PdfWriter::new();
let catalog = writer.catalog();
let page_tree = writer.pages();
let page = writer.page(MediaBox::new(0.0, 0.0, 595.0, 842.0));
page.parent(page_tree);
page_tree.add_page(page);
catalog.pages(page_tree);
writer.finish();
std::fs::write("empty.pdf", writer.finish()).unwrap();
}