QuestPDF силен, когда граница продукта — C#
QuestPDF заслуживает уважительного сравнения. Это современная библиотека генерации PDF для C#-разработчиков: fluent API, строгая типизация, большая документация, Companion App для предпросмотра и отладки, а также необычно понятная для PDF SDK модель лицензирования.
Вопрос не в том, какой продукт умеет создавать PDF. Оба умеют. Полезный вопрос — где должна проходить граница PDF: внутри .NET-приложения, которое владеет макетом, байтами и жизненным циклом, или на уровне инфраструктурного сервиса, к которому обращаются разные продукты и языки программирования.
Быстрый выбор
- Выбирайте QuestPDF, если C# является источником истины для документа, приложение должно работать офлайн или нужны локальные операции над существующими PDF.
- Выбирайте gPdf, если один PDF-слой должен обслуживать Node, Python, Go, .NET, фоновые задачи и региональные системы через один HTTP API.
- Выбирайте gPdf, если изменения макета должны быть версиями шаблона, а не пересборкой C# и повторным развертыванием сервиса.
Одна семья документов, разные модели владения
С QuestPDF приложение владеет генерацией PDF — это сильная сторона: C# находится рядом с доменной моделью, все запускается и отлаживается локально, без вызова внешнего API во время выполнения.
Компромисс в том, что команда владеет и всем боевым контуром:
- CPU и памятью для рендера.
- Поиском шрифтов и цепочками подстановки в каждой среде развертывания.
- Интеграцией библиотеки штрихкодов и проверкой печати.
- Нативными пакетами и вопросами развертывания для графиков или пользовательской графики.
- Мониторингом, повторами и обработкой отказов.
- Региональным развертыванием, если пользователи или склады распределены по миру.
- Выпусками при каждом изменении макета документа.
С gPdf эта область выносится наружу: приложение отправляет DocumentRequest или template_id + data, а сервис отвечает за рендерер, среду выполнения на edge, шрифты, примитивы штрихкодов, вывод PDF/A и упаковку электронных счетов. Это менее привлекательно, если вы хотите держать каждую деталь в C#, но лучше подходит, когда генерация PDF должна быть общим служебным слоем, вызываемым из любого стека.
Три компромисса, на которые хостинговый API должен отвечать честно
Большинство сравнений библиотеки и API обходят три вопроса, которые .NET-архитектор задает первыми. Честное сравнение проговаривает их напрямую.
1. Куда уходят данные документа. Эта страница в основном про счета, выписки и электронные счета — документы с именами, адресами, налоговыми идентификаторами и суммами. В QuestPDF эти байты создаются внутри вашего процесса и не покидают его. Публичный API gPdf передает тело запроса рендереру, но рендерер работает без хранения: JSON запроса находится в V8-изоляте Cloudflare Workers только во время рендера (обычно ~4 ms) и освобождается после завершения ответа — не сохраняется, не логируется, не попадает в выборки и не используется для обучения; операционные логи ограничены HTTP-статусом и длительностью (security, DPA). Выбор размещения данных в ЕС / глобально и enterprise on-prem / частное развертывание дополнительно сужают или закрывают внешний контур. Тем не менее генерация внутри процесса без настройки — вполне законная, иногда решающая причина, по которой финансовая или государственная команда выбирает QuestPDF.
2. Режим отказа. У библиотеки нет третьей стороны, которая может упасть; генерация может сломаться только на инфраструктуре, которой вы уже владеете. Хостинговый API добавляет зависимость от доступности поставщика, которую вы не контролируете. Правильный способ внедрять gPdf — относиться к вызовам рендера как к любому внешнему вызову: таймаут, повтор, очередь и, в идеале, деградированный резервный путь. Если генерация документов стоит на критическом синхронном пути, сравнивайте “эксплуатировать самим” с “зависеть от доступности поставщика”.
3. Профиль задержки. Генерация внутри процесса — это вызов функции без сети. Размещенный вызов — сетевой обмен туда-обратно. Для пакетных и асинхронных задач это шум. Для сценария “пользователь нажал кнопку, PDF должен появиться сейчас” генерация внутри процесса структурно быстрее; edge PoPs gPdf делают переход небольшим, но это все равно TLS плюс сетевой обмен, тогда как QuestPDF — вызов метода.
Это не делает gPdf неправильным выбором; это определяет, когда он правильный — для команд, чьи данные документов могут покидать процесс, чьи процессы выдерживают сетевой переход и которым выгоднее зависеть от доступности поставщика, чем самим эксплуатировать парк рендереров.
Лицензирование и модель цены
Публичная страница лицензирования QuestPDF говорит, что коммерческая лицензия требуется только компаниям с годовой валовой выручкой выше 1 млн USD. Уровень Community бесплатен по MIT-условиям для подходящих частных лиц, open-source-проектов, некоммерческих организаций и компаний ниже этого порога. На той же странице указаны два бессрочных коммерческих уровня: Professional за 999 USD плюс местные налоги для команд до 10 разработчиков и Enterprise за 2 999 USD плюс местные налоги на всю организацию без подсчета разработчиков. Оба тарифа включают один год обновлений и неограниченные проекты, серверы и развертывания, а лицензия не истекает для последней полученной версии.
Модель контроля тоже необычно легкая. Лицензия задается одной строкой — QuestPDF.Settings.License = LicenseType.Community; — без лицензионного ключа, сервера активации и, согласно собственной странице конфигурации QuestPDF, без сетевых вызовов и без вывода данных с машины. Это модель на доверии: вы выбираете уровень, на который имеете право. Нет счета поставщика за каждый документ, а платная лицензия работает где угодно, включая полностью офлайн.
gPdf тарифицирует сам сервис рендера. Публичный Basic plan начинается с 5 USD/мес. за 100 000 страниц, перерасход — от 0,00005 USD за страницу. Это счет поставщика, но он также убирает отдельный проект по эксплуатации генерации PDF: без кластера рендера, без пути развертывания NuGet, без регионального теплого пула, без пакета шрифтов для каждого приложения и без PDF-сервиса, который нужно патчить.
Поэтому сравнение стоимости — не “999 USD против 5 USD”; лицензия — малая строка. Реальное сравнение такое:
Стоимость QuestPDF = лицензия (разовая) + ваш хостинг + время инженеров + дежурства
Стоимость gPdf = счет за страницы (инфраструктура, шрифты, масштабирование и edge включены)
По публичной постраничной модели gPdf перерасход стоит 0,05 USD за 1 000 страниц (50 USD за 1 млн, 500 USD за 10 млн). Разовая лицензия Enterprise за 2 999 USD сравняется с этим счетом только примерно на 60 млн страницах — и этот расчет не учитывает хостинг QuestPDF и инженерные месяцы, которые сдвигают реальную точку пересечения дальше в пользу gPdf, если у вас уже нет почти бесплатной инфраструктуры рендера. Практическое правило: если ради библиотеки нужно построить и укомплектовать сервис рендера, gPdf обычно выигрывает по полной стоимости задолго до того, как постраничный счет догонит лицензию; если эта инфраструктура уже есть и почти бесплатна, бессрочная лицензия выигрывает на масштабе.
Процесс разработки: Fluent C# против шаблонов
Fluent API QuestPDF хорошо подходит, когда разработчики владеют формой документа. Строгая типизация, цепочки методов, переиспользуемые C# компоненты, рефакторинг в IDE и Companion App логичны, если PDF является частью кодовой базы приложения.
gPdf подходит другому процессу. Разработчики могут писать JSON напрямую, но боевые системы обычно переходят к шаблонам. Дизайнер, операционный специалист или инженер настраивает макет в gPdf Studio. Утвержденный макет становится шаблоном, а бэкенд продолжает рендерить через template_id + data.
Эта разница важна, когда документ часто меняется. Если меняется этикетка перевозчика, счет, упаковочный лист или макет выписки, gPdf может оставить среду выполнения стабильной и изменить только шаблон. В QuestPDF макет — это C# код, поэтому обычный путь: изменение кода, тест, сборка, развертывание и план отката.
Ни один процесс не лучше всегда: QuestPDF оптимизирован для C# разработчиков, которым нужен документ как код; gPdf — для операционных шаблонов, общих для нескольких систем.
Соответствие требованиям: оба продукта серьезные
Это не сравнение, где gPdf выигрывает заявлением, что у конкурента нет функций соответствия требованиям. Текущие публичные материалы QuestPDF перечисляют сильную поддержку стандартов, включая PDF/A, PDF/UA-1 и электронные счета EN 16931 через пример ZUGFeRD 2.1 / Factur-X на базе UN/CEFACT Cross Industry Invoice (CII). Этот пример включает PdfA = true, встраивает тело factur-x.xml через AddAttachment(), дополняет документ XMP-метаданными и валидирует результат через veraPDF (для PDF/A-3b) и Mustang Project (для ZUGFeRD). Это полный и честный рецепт — и ваш процесс владеет каждым его шагом.
gPdf упаковывает те же стандарты как API-контракт. JSON Render открывает шесть профилей PDF/A (1b, 2b, 3b, 4, 2u, 3u) плюс PDF/UA-1 через settings.profile, Template Render переиспользует ту же модель документа, а E-Invoice Render дает выделенный эндпоинт POST /api/v1/e-invoice/render, который создает пакеты Factur-X / ZUGFeRD PDF/A-3b со встроенным EN 16931 CII XML. Отличие от рецепта QuestPDF в том, что сервис делает за вас: gPdf выполняет PDF/A-3b и валидацию электронного счета на сервере, поддерживает синхронную выдачу в ответе или доставку через опрашиваемый объект и предлагает резидентность данных в ЕС или глобально как параметры запроса, а не как шаги, которые вы собираете и эксплуатируете. QuestPDF подходит, когда валидация должна жить внутри вашего .NET-процесса; gPdf — когда это должен быть хостинговый контракт, общий для многих систем.
Шрифты и штрихкоды: главное — усилия интеграции
У QuestPDF сильная модель шрифтов. Он поставляет Lato 2.015 по умолчанию, автоматически загружает системные шрифты и шрифты из каталога развертывания, позволяет регистрировать пользовательские шрифты через FontManager и поддерживает цепочки подстановки. Это дает разработчикам контроль. Но та же документация честно описывает проблему: “in most cloud deployments, few or no fonts are available, which may lead to unexpected results” и рекомендует отключать шрифты окружения и явно регистрировать нужные. Иначе говоря, в контейнере или бессерверной среде шрифтовое окружение — ваша зона планирования, упаковки и тестирования; отсутствующий глиф станет символом-заглушкой или, если включить CheckIfAllTextGlyphsAreAvailable, исключением.
gPdf делает шрифты частью границы сервиса. Рендерер включает набор для многих письменностей — латиницы, греческого, кириллицы, арабского, иврита, бенгальского, тамильского, тайского, вьетнамского, моноширинного текста и CJK с подстановкой по письменности на Noto KR / JP / SC. Он решает неявный выбор шрифта через авто-выбор, а явный выбор — через prefer или strict. Вызывающим приложениям не нужно отправлять CJK-шрифт, регистрировать ресурсы Noto в .NET-приложении или настраивать подстановку для каждой среды развертывания. Они отправляют данные; рендерер владеет шрифтовым окружением, одинаковым в каждом регионе.
Сравнение штрихкодов имеет похожую форму. Документация QuestPDF по штрихкодам показывает добротный подход с ZXing.Net, который рендерится как векторный SVG, и прямо отмечает, что ZXing.Net не входит в пакет QuestPDF — его устанавливают из NuGet и подключают отдельно:
// QuestPDF: add the separate ZXing.Net package, encode, render to SVG, embed.
// dotnet add package ZXing.Net
var writer = new ZXing.BarcodeWriterSvg {
Format = ZXing.BarcodeFormat.CODE_128,
Options = new ZXing.Common.EncodingOptions { Width = 320, Height = 80 }
};
string svg = writer.Write("INV-2026-001").Content;
container.Svg(svg);
// GS1-128 with Application Identifiers and FNC1 framing is hand-wired on top.
В gPdf генерация штрихкодов — полноценный элемент схемы. Запрос объявляет формат, содержимое, физический размер и опциональную человекочитаемую строку; форматы GS1 нативные, поэтому идентификаторы применения идут прямо в content:
{
"type": "barcode",
"format": "gs1_128",
"content": "(01)00012345678905(21)SN12345",
"x": 12, "y": 60, "width": 80, "height": 18,
"barcode_text": { "enabled": true, "position": "bottom" }
}
Для одного .NET приложения установить ZXing.Net и протестировать вывод может быть легко. Для многих сервисов и шаблонов — особенно в логистике и рознице, где нужны GS1-128, SSCC, GTIN, GS1 DataMatrix или GS1 QR с человекочитаемой строкой интерпретации — проще поддерживать поведение штрихкодов внутри API документов, чем заново подключать ZXing в каждом сервисе.
Где QuestPDF явно выигрывает
Помимо офлайн-работы, удержания данных документа внутри вашего периметра и сценариев, где PDF-код сам является частью продукта, QuestPDF уверенно сильнее в двух областях возможностей, которые находятся вне области gPdf:
- Операции с существующими PDF. QuestPDF может загружать существующие файлы и объединять их, выбирать / переставлять / разворачивать / фильтровать страницы, накладывать оверлеи, добавлять вложения, задавать XMP-метаданные, линеаризовать для web-доставки, а также шифровать и расшифровывать с безопасностью 40/128/256-bit. gPdf может ставить пароль и ограничивать права для PDF, которые он генерирует, но не открывает, не объединяет и не расшифровывает файлы, созданные не им.
- Графики, карты и пользовательская графика. QuestPDF интегрирует библиотеки графиков (ScottPlot, LiveCharts, Microcharts), встраивает карты Mapbox и открывает SkiaSharp canvas для произвольного 2D-рисования. gPdf может рисовать векторную графику через элемент
path(SVG path data) или встраивать SVG / PNG-график, созданный выше по процессу, но у него нет встроенного движка графиков, карт или canvas — поэтому если графики на данных являются центральной частью документа, этот инструментарий остается на стороне QuestPDF.
Где gPdf явно выигрывает
gPdf выигрывает, когда организация не хочет, чтобы каждая продуктовая команда владела собственным PDF-сервисом: стеки на нескольких языках программирования, глобальные процессы и ERP / OMS / WMS / ecommerce / fintech / ticketing-системы, которые рендерят документы из структурированных данных, с шаблонами, меняющимися независимо от кода. В таких условиях локальная библиотека часто начинается дешево, а затем превращается в парк: один сервис на язык программирования, один путь развертывания на регион, один план шрифтов на контейнер, один набор регрессий штрихкодов на команду. gPdf превращает этот парк в один HTTP-контракт.
Бессерверная архитектура делает границу особенно явной. На AWS Lambda, Cloud Run или Azure Functions QuestPDF все равно работает внутри приложения — команда пакует среду выполнения .NET, шрифты, нативные зависимости и достаточно CPU / памяти для пиковых PDF-задач, а также отвечает за холодные старты. gPdf уже является сервисом рендера: функция отправляет небольшой запрос template_id + data на edge и получает PDF-байты обратно, без рендерера, который нужно прогревать, и без воркера в каждом регионе, который нужно масштабировать.
Как выглядит миграция
Миграция с QuestPDF на gPdf — не построчная перепись. Это смена границы: C# код, строящий PDF, становится либо JSON-запросом документа, либо опубликованным шаблоном.
До / после — C# вызов сборки документа сводится к одному HTTP POST (нажмите, чтобы раскрыть)
- // Before: generate the PDF inside a .NET application.
- Document.Create(container =>
- {
- container.Page(page =>
- {
- page.Size(PageSizes.A4);
- page.Margin(30);
- page.Header().Text("Invoice").FontSize(24).SemiBold();
- page.Content().Column(column =>
- {
- column.Item().Text($"Invoice number: {invoice.Number}");
- column.Item().Text($"Total: {invoice.Total:C}");
- });
- });
- })
- .GeneratePdf("invoice.pdf");
+
+ // After: render through the shared gPdf template from C#.
+ using System.Net.Http.Headers;
+ using System.Net.Http.Json;
+
+ using var client = new HttpClient();
+ client.DefaultRequestHeaders.Authorization =
+ new AuthenticationHeaderValue("Bearer", key);
+
+ var response = await client.PostAsJsonAsync(
+ "https://api.gpdf.com/api/v1/template-render",
+ new {
+ template_id = "invoice-v2",
+ data = new {
+ invoice_number = invoice.Number,
+ total = invoice.Total,
+ currency = invoice.Currency
+ }
+ });
+
+ response.EnsureSuccessStatusCode();
+ byte[] pdfBytes = await response.Content.ReadAsByteArrayAsync();
Когда эта граница переносится, изменения макета могут стать версиями шаблона вместо развертываний приложения. Приложение по-прежнему владеет бизнес-данными и решениями процесса; gPdf владеет рендерингом.
Примечание о ценах и источниках
Информация о QuestPDF на этой странице проверена 2026-06-02 по официальным источникам QuestPDF: License and Pricing, License configuration, Features Overview, Companion App features, Barcodes, Font management и ZUGFeRD example. Цены и страницы возможностей могут меняться; закупочным командам стоит перепроверить страницу поставщика перед решением о покупке. QuestPDF и связанные обозначения принадлежат их владельцам, это сравнение ими не одобрено.
Связанные сценарии генерации PDF
Если вы сравниваете QuestPDF и gPdf, рядом обычно возникают задачи API JSON в PDF, PDF счетов, API транспортных этикеток, GS1-128 и штрихкодов в PDF, API PDF/A, API Factur-X и генерации PDF без эксплуатации собственного сервиса рендера. Также полезно посмотреть отдельный разбор стоимости транспортных этикеток на iText и gPdf, если ваш сценарий ближе к логистике.
FAQ
Заменяет ли gPdf QuestPDF?
Нет. gPdf заменяет необходимость эксплуатировать сервис генерации PDF для структурированных бизнес-документов. QuestPDF остается сильной локальной C# библиотекой, когда PDF должен генерироваться внутри приложения.
QuestPDF бесплатен?
Публичная страница лицензирования QuestPDF говорит, что уровень Community бесплатен по MIT-условиям для подходящих частных лиц, open-source-проектов, некоммерческих организаций и компаний с годовой валовой выручкой ниже 1 млн USD. Компаниям выше этого порога нужна бессрочная коммерческая лицензия: Professional за 999 USD плюс местные налоги для команд до 10 разработчиков или Enterprise за 2 999 USD плюс местные налоги на всю организацию, каждый вариант включает один год обновлений.
Может ли gPdf генерировать графики или карты как QuestPDF?
Не как встроенный движок. QuestPDF интегрирует библиотеки графиков (ScottPlot, LiveCharts, Microcharts), карты Mapbox и SkiaSharp canvas, которые рендерятся внутри документа. gPdf все еще может рисовать векторные графики через элемент path (принимает SVG path data) и фигуры или встраивать SVG / PNG, созданный любой библиотекой визуализации, как image. Разница в том, что QuestPDF вычисляет и рендерит график внутри процесса, а с gPdf вы создаете графику, и gPdf размещает ее. Если графики на данных или карты являются центральными для документа, QuestPDF подходит лучше.
Какой продукт дешевле?
Зависит от границы. QuestPDF может быть дешевле для .NET-команд, которые подходят под условия Community или уже эксплуатируют инфраструктуру рендера. gPdf может быть дешевле, когда альтернатива — построить, разместить и обслуживать PDF-сервис для нескольких продуктов или регионов.
Хранит или логирует ли gPdf данные моих документов?
Нет. JSON, который вы отправляете, и PDF, который возвращает gPdf, не сохраняются. Каждый запрос рендерится внутри одного V8-изолята Cloudflare Workers, держится в памяти только во время рендера — обычно около 4 ms — и освобождается после завершения потока ответа; gPdf не сохраняет, не логирует, не берет выборки и не обучается на содержимом DocumentRequest. Операционные логи хранят только HTTP-статус и длительность 30 дней и не содержат тел запросов. См. security policy, privacy policy и DPA. Для нагрузок, которые вообще не могут передавать данные наружу, on-prem / частное развертывание удерживает их внутри вашего периметра.
Может ли QuestPDF работать без доступа к интернету?
Да. Страница конфигурации лицензии QuestPDF говорит, что лицензионный ключ и сервер активации не нужны, а вычисления выполняются локально. Это одна из самых ясных причин выбрать QuestPDF.
Может ли gPdf рендерить произвольные C# макеты QuestPDF?
Нет. gPdf не выполняет C# код макета. Миграция означает перевод формы документа в gPdf JSON-запрос или сохраненный gPdf шаблон.