Генерация PDF на сервере: FastReport, QuestPDF, шаблоны

↑ 5.6 Генерация документов и отчётов · → Следующая

Желательно~3 мин чтенияУровень: middle

Зачем это на собесе

Практический кейс: счета, акты, справки. Спрашивают, чем генерировать и как не положить сервис нагрузкой.

Объяснение

ПодходПлюсыМинусы
QuestPDF (код на C#, fluent API)типобезопасно, тесты, без внешних зависимостейвёрстка кодом; лицензия для коммерции (Community — до порога дохода)
FastReport / отчёты по шаблонамдизайнер шаблонов, бизнес правит самкоммерческая лицензия, движок тяжёлее
HTML → PDF (Chromium/Playwright, wkhtmltopdf)вёрстка HTML/CSS, знакомо фронтендерамтяжёлый браузер, потребление памяти
iText / PDFsharpнизкоуровневый контрольбольше кода, AGPL у iText
Word/ODT → PDF (LibreOffice)шаблоны в Wordмедленно, внешний процесс
Document.Create(c => c.Page(page =>
{
    page.Size(PageSizes.A4); page.Margin(30);
    page.Header().Text($"Счёт № {inv.Number}").FontSize(20).Bold();
    page.Content().Table(t =>
    {
        t.ColumnsDefinition(cd => { cd.RelativeColumn(4); cd.RelativeColumn(); cd.RelativeColumn(); });
        foreach (var i in inv.Items) { t.Cell().Text(i.Title); t.Cell().Text(i.Qty.ToString()); t.Cell().Text(i.Total.ToString("N2")); }
    });
    page.Footer().AlignCenter().Text(x => { x.CurrentPageNumber(); x.Span(" / "); x.TotalPages(); });
})).GeneratePdf(stream);

Архитектура:

  • Генерация тяжёлая (CPU/память): выносите в фоновый воркер, очередь задач, ограничивайте параллелизм.
  • Результат сохраняйте в объектное хранилище и отдавайте по ссылке (см. Хранение и отдача файлов через MinIO).
  • Шаблон и данные разделены: данные собираются отдельной моделью (view model).
  • Шрифты со встроенной кириллицей включайте явно.

Нюансы и подводные камни

  • Кириллица и шрифты: без встроенного шрифта в контейнере вместо букв «квадратики».
  • Генерация в HTTP-запросе на большом документе блокирует пул и вызывает таймауты.
  • Повторная генерация одного документа: кэшируйте по хэшу данных и версии шаблона.
  • PDF/A для архивного хранения, подписи и ЭЦП — отдельные требования.
  • Тестируйте визуально (снимки страниц) и по тексту.

Практика

  1. Сгенерируйте счёт через QuestPDF со шрифтом с кириллицей.
  2. Вынесите генерацию в фоновый воркер и статус задачи в API.
  3. Сравните время и память QuestPDF и HTML→PDF на 500 страницах.

Вопросы с ответами

Связанные темы