DynamicPDF Core Suite позволяет из кода создавать PDF с текстом, таблицами, изображениями, формами, штрихкодами и подписями, объединять и разбирать существующие документы, заполнять поля, ставить водяные знаки, извлекать содержимое и строить отчёты по DLEX-шаблонам. Основная работа ведётся через объектную модель Document, Page и PageElements, а визуальная часть подготовки отчётов выполняется в Designer, где макет связывается с данными и проверяется до подключения к проекту.
Практический процесс обычно начинается с выбора источника: новый документ собирают из страниц и элементов, готовый PDF открывают через классы слияния и импорта, а повторяемый отчёт проектируют как страницу или секционный макет. Результат можно записать в файл, поток или массив байтов, поэтому одна и та же логика подходит для фоновой службы, веб-обработчика, настольной системы документооборота и пакетной задачи.
В Designer рабочая область разделена на полотно, дерево документа, свойства и проводник данных. Статические надписи добавляются как Label, поля набора данных — как RecordBox или RecordArea, повторяющиеся строки располагаются в Detail, а Header и Footer управляют содержимым каждой страницы. Кнопка Run Report соединяет DLEX с тестовыми данными и показывает итоговый PDF, что помогает увидеть переполнение, неверные отступы и разрывы ещё до запуска серверного кода.
Скачать DynamicPDF Core Suite
- Редактирование PDF
- Русский интерфейс
- Просто новичкам
- Нет готового PDF-редактора
- Печать требует PrintManager
- Часть функций по лицензии
Как устроен рабочий процесс
В коде документ выступает контейнером для страниц, параметров безопасности, метаданных, шаблонов и настроек вывода. Страница задаёт геометрию и хранит коллекцию элементов; порядок добавления влияет на наложение, поэтому фон помещают раньше текста, а печать поверх импортированного бланка — после области исходной страницы. Такой порядок удобен для счетов, актов и сертификатов: сначала импортируется основа, затем поверх неё размещаются значения, подпись, штамп или служебная отметка.
При обработке готового файла важно отделять импорт страницы от слияния документов. Импорт одной страницы нужен для титула, вложенного бланка или размещения нескольких миниатюр на листе. Слияние сохраняет последовательность выбранных страниц и способно переносить аннотации, слои, встроенные файлы, поля форм и логическую структуру при подходящих настройках. Если исходник содержит пароль, его передают при открытии, а разрешения проверяют до попытки извлечь или изменить данные.
Для отчётов Designer формирует DLEX — XML-описание расположения элементов и секций. Во время выполнения DocumentLayout загружает этот макет, получает данные и возвращает обычный Document. После Layout к результату можно применить те же операции, что и к документу, созданному вручную: добавить страницу, зашифровать, подписать, объединить с приложениями или сохранить в поток ответа.

Подключение библиотеки к проекту
Пакет подключается через NuGet или как набор сборок. Для нового проекта удобнее PackageReference: менеджер зависимостей выбирает подходящую сборку для целевой платформы и переносит необходимые зависимости при публикации. При ручном подключении нужно следить, чтобы в выходной каталог попала сборка, соответствующая целевой среде, а у веб-приложения были права на чтение шрифтов, шаблонов и входных PDF.
Поддерживаемая база охватывает .NET Framework начиная с 4.6.2, .NET Standard 2.0 и современные версии .NET. Это позволяет вынести общую логику генерации в библиотеку классов, которую используют ASP.NET Core, служба Windows, консольная задача и другие .NET-приложения. При выборе target framework следует учитывать не только компиляцию, но и доступность системных шрифтов, криптографических провайдеров и путей к ресурсам на целевой машине.
Лицензионный ключ добавляют до первой операции вывода. В веб-проекте это делают один раз при запуске приложения, а не перед каждой страницей. Если ключ отсутствует, не соответствует окружению или не покрывает используемую функцию, итог может содержать демонстрационную отметку либо операция сообщит о лицензионном ограничении. Поэтому проверку лицензии полезно включить в стартовую диагностику и журналировать логический результат AddLicense без записи самого ключа.
using ceTe.DynamicPDF;
public static class PdfRuntime
{
public static void Configure(string licenseKey)
{
bool accepted = Document.AddLicense(licenseKey);
if (!accepted)
throw new InvalidOperationException("Ключ DynamicPDF не принят");
}
}
Первый документ: страницы, координаты и вывод
Минимальная схема состоит из Document, одной Page и элемента Label. Координаты и размеры задаются в пунктах: 72 пункта соответствуют одному дюйму. Начало координат относится к верхнему левому углу полезной области страницы с учётом её полей. Это отличается от графических систем, где вертикальная ось направлена вверх, поэтому перенос координат из чертежа или SVG обычно требует пересчёта.
Размер страницы можно выбрать из готового набора либо задать вручную. Для форматов A4 и Letter следует сразу согласовать поля, ориентацию и область для колонтитулов. Если элементы начинают выходить за границы, причина часто не в шрифте, а в том, что ширина задана от края бумаги, хотя фактическая точка отсчёта уже смещена полем. На этапе прототипа помогает временный LayoutGrid или тонкие прямоугольники, показывающие границы блоков.
Document.Draw записывает документ в файл, а перегрузки позволяют вернуть массив байтов или вывести данные в поток. В серверной задаче предпочтителен поток, потому что он не требует сначала создавать временный файл. Для больших документов лучше не вызывать генерацию дважды: результат нужно получить один раз и передать дальше, иначе повторная верстка увеличит время и память.
var document = new Document();
var page = new Page(PageSize.A4, PageOrientation.Portrait, 36);
page.Elements.Add(new Label(
"Счёт сформирован автоматически",
0, 0, 523, 24, Font.HelveticaBold, 14, TextAlign.Center));
document.Pages.Add(page);
document.Draw("invoice.pdf");
Рабочая область Designer
При открытии Designer без макета появляется File Explorer. Здесь создают DLEX, открывают сохранённый шаблон и загружают связанные ресурсы. Если JSON-файл имеет то же базовое имя, что и DLEX, тестовые данные могут подхватиться автоматически. Это удобно для хранения пары макет плюс пример, но в рабочем репозитории всё равно стоит фиксировать отдельную схему данных, чтобы дизайнер и разработчик одинаково трактовали названия и типы полей.

Верхняя панель содержит создание и открытие файла, сохранение, буфер обмена, отмену и повтор, масштаб, просмотр исходника DLEX, редактор данных, запуск отчёта, настройки и справку. Просмотр исходника полезен при поиске трудноуловимой ошибки: можно увидеть фактические id, dataName, размеры и порядок элементов. Окно исходника предназначено для чтения; ручное исправление выполняют после выгрузки файла, а затем возвращают DLEX в хранилище.

Правая сторона объединяет Document Explorer, Properties и Data Explorer. В дереве выбирают документ, страницу, отчёт, секцию или конкретный элемент; панель свойств меняется в зависимости от выбора. Data Explorer строится по тестовому набору и показывает одиночные поля и повторяющиеся массивы. Перетаскивание поля создаёт связанный RecordBox, что снижает риск опечатки в dataName.
Подготовка данных для DLEX
Designer требует тестовые данные, потому что без них невозможно построить дерево полей и проверить повторяющиеся секции. Для макета данные представляют в JSON: одиночные свойства верхнего уровня подходят для фиксированной страницы или заголовка, а массивы — для Detail отчёта и подотчётов. Тестовый набор должен включать не только типичный случай, но и длинные строки, пустые значения, нулевые суммы и достаточное число записей для перехода на следующую страницу.

В рабочем коде LayoutData может формироваться не только из JSON. После того как структура DLEX готова, данные можно передавать через поддерживаемые объекты и источники, но имена должны совпадать с тем, что указано в макете. Переименование поля в модели без синхронного изменения DLEX обычно проявляется как пустой RecordBox, а не как ошибка компиляции, поэтому полезен автоматический тест, который генерирует отчёт и проверяет наличие контрольных значений.
Для денежных и датовых полей формат лучше задавать на уровне RecordBox или выражения, а не заранее превращать всё в строки. Тогда агрегаты получают числа, сортировка не путает значения, а один макет можно использовать с разной культурой при явной настройке формата. Если в данных встречаются свойства с дефисом или имя начинается с цифры, в выражениях применяют специальную запись поля, иначе парсер может принять имя за операцию.
Страницы и отчёты в одном макете
Page и Report решают разные задачи. Страница предназначена для фиксированного расположения: титульный лист, сертификат, пропуск, заполнение готового бланка. На ней доступны статические элементы и неповторяющиеся поля верхнего уровня. Report рассчитан на набор записей: его Detail повторяется, а Header и Footer формируют повторяемые области каждого листа.

Отчёт создаётся кнопкой Add Report и получает секции заголовка, деталей и нижнего колонтитула. Свойство dataName указывает повторяющийся массив. Поля из массива размещают в Detail, а общие сведения — в Header или на отдельной странице. При неверном выборе области итог часто выглядит так: первая строка отображается, а остальные пропадают, либо общий заголовок повторяется для каждой записи.
Колонки управляются свойствами columns, columnSpacing и columnLayout. horizontal заполняет колонки слева направо и не допускает разрыва записи; verticalUneven сначала заполняет первую колонку, затем следующую; verticalEven выравнивает заполнение последней страницы. Для справочников и этикеток выбор режима заметно влияет на порядок чтения, поэтому его нужно проверять на количестве записей, которое не делится на число колонок.

Добавление элементов в макет
Контекстное меню рабочей области предлагает штрихкод, ContentGroup, FormattedRecordArea, Image, Label, Line, NoSplitZone, PageBreak, PageNumberingLabel, RecordArea, RecordBox, Rectangle, SoftBreak, Subreport и Symbol. Недоступные элементы отображаются неактивно, если выбранная секция не поддерживает их. Например, повторяющиеся поля массива нельзя корректно разместить на фиксированной странице; их место — в отчёте.

Label хранит постоянный текст, а RecordBox выводит значение или результат выражения. RecordArea нужен для многострочного текста с продолжением. FormattedRecordArea применяют, когда данные содержат поддерживаемую разметку и должны переноситься с форматированием. У каждого элемента есть id, координаты, ширина и высота; текстовые элементы также управляют шрифтом, размером, выравниванием, направлением и вертикальным положением.
Перетаскивание поля из Data Explorer сразу связывает его с источником. После создания следует проверить ширину, высоту и свойства расширения. Слишком маленькая высота приводит к обрезанию, а бесконтрольное расширение может вытолкнуть соседние элементы и вызвать неожиданный перенос. Для строк таблицы разумно сначала определить максимальную допустимую высоту, затем решить, разрешено ли деление строки между страницами.

Разметка страницы и свойства геометрии
Свойства страницы включают ширину, высоту, ориентацию, формат и четыре поля. Значения задаются в пунктах. Для пользовательского бланка следует измерять не только бумагу, но и координаты печатной области: принтер может физически не воспроизводить содержимое у края, хотя PDF формально его допускает. Если файл предназначен для просмотра, важнее единообразие полей; если для печати — контроль реального оборудования.

Пара templatePath и templatePageNumber подключает конкретную страницу исходного PDF как фон. Это позволяет использовать утверждённый фирменный бланк и наносить поверх него динамические значения. После подключения нужно подогнать поля и высоту секций под зоны шаблона. Несовпадение размеров проявляется смещением линий, наложением Detail на нижнюю часть бланка или лишней пустой областью.
При изменении ориентации уже расставленного макета координаты не становятся автоматически оптимальными. Элементы следует проверить вручную или вычислять позиции относительно ширины страницы. В кодовой генерации удобно использовать функции, возвращающие правую границу и центр; в DLEX аналогичную устойчивость обеспечивают согласованные размеры блоков и минимальное число абсолютных поправок.
Работа с PDF-шаблонами
PDF-шаблон полезен, когда внешний вид утверждён отдельно от кода: договорная форма, счёт, лабораторный бланк или сертификат. Designer показывает выбранную страницу, после чего поверх неё размещаются поля и повторяющиеся области. Сам шаблон не знает о данных, поэтому вся связь находится в DLEX: координаты, dataName, формат и условия отображения.

Header, Detail и Footer должны совпасть с геометрией бланка. Header повторяется на каждой странице отчёта, Footer также повторяется, а Detail создаётся для каждой записи. Если фирменная шапка нужна только на первой странице, используют условный заголовок или отдельную фиксированную страницу. Если итоги должны появляться только в конце, применяют условный нижний колонтитул, а не обычный Footer.
В свойствах шаблона задаются идентификатор, путь и номер страницы. Путь следует трактовать как ресурс приложения, а не как случайный абсолютный путь с компьютера разработчика. В контейнере, службе и веб-хостинге рабочая директория может отличаться, поэтому безопаснее рассчитывать путь от каталога приложения или передавать ресурс потоком, если соответствующий сценарий поддерживает выбранный API.

Текст, шрифты и многоязычные документы
Для простых подписей подходят встроенные PDF-шрифты, но кириллица, расширенный Unicode и фирменная типографика требуют подходящего OpenType или TrueType-шрифта. Библиотека поддерживает встраивание целиком, подмножество и отказ от встраивания. Подмножество уменьшает файл, однако документ, который позже дополняется другим процессом, может потребовать повторного встраивания недостающих глифов.
Unicode сам по себе не гарантирует правильный результат. Нужно, чтобы выбранный шрифт содержал глифы, а механизм формирования текста корректно обработал направление и соединение символов. Поддерживаются текст справа налево и character shaping; для арабского, персидского и некоторых индийских письменностей следует тестировать не отдельные слова, а полноценные строки с цифрами, знаками пунктуации и смешанным направлением.
TextArea работает с обычным текстом и переносами, FormattedTextArea понимает ограниченную HTML-разметку, а HTMLArea предназначен для поддерживаемого HTML-содержимого. Это не замена браузерному движку: сложные CSS-сетки, сценарии и поведение современного веб-приложения нельзя переносить в такой элемент без проверки. Если источник — большой веб-шаблон, целесообразно отдельно оценить специализированный HTML-конвертер; Core Suite сильнее в объектной разметке PDF и отчётах.
Проблемы с переносом строк чаще всего вызывают три фактора: ширина блока меньше ожидаемой, метрики фактического шрифта отличаются от макетного шрифта, либо в тексте есть неразрывные фрагменты. Диагностику начинают с вывода рамки элемента и замены текста на контрольную строку. Если рамка верна, проверяют файл шрифта, его регистрацию в ресурсном провайдере и правила переноса для конкретной письменности.
Изображения и качество печати
Поддерживаются JPEG, JPEG 2000, PNG, BMP, EMF, EXIF, GIF, TIFF, многостраничный TIFF и WMF; изображения можно читать из файла, потока или массива байтов. В макете Image получает статический path или динамическое значение. Данные могут приходить как Base64, относительный путь либо другой поддерживаемый источник, что удобно для подписей, фотографий товаров и печатей.
Масштабирование не создаёт дополнительных пикселей. Если исходник 300×300 размещён с масштабом один пиксель на пункт, его эффективное разрешение около 72 dpi. Для 300 dpi масштаб должен соответствовать отношению 72 к 300. Растягивание маленького логотипа до ширины страницы даст размытый результат независимо от качества PDF-контейнера; для схем предпочтительнее векторный источник, а для фотографии — достаточное растровое разрешение.
Параметры shrinkToFit и expandToFit помогают вписать изображение, но могут изменить ожидаемую плотность или оставить пустые поля при сохранении пропорций. Для паспортной фотографии, штрихкода и подписи правила различаются: фотографию обычно кадрируют или вписывают, штрихкод нельзя непропорционально растягивать, а подпись должна сохранить прозрачность и не закрыть подпись владельца формы.
При пакетной генерации одинаковый логотип следует повторно использовать через шаблон или механизм разделения ресурсов, а не декодировать заново для каждой страницы. Функция sharing шрифтов и оптимизация изображений помогают сократить размер, но итог нужно проверять визуально: агрессивное уменьшение изображения может быть приемлемо для экрана и неприемлемо для печати мелкого текста.
Таблицы, списки и продолжение на страницах
Table2 поддерживает автоматические размеры ячеек, раздельное оформление границ, внутренние отступы, изображения и другие элементы внутри ячейки, вложенные таблицы и форматированный текст. Главное практическое отличие от ручного рисования линий состоит в продолжении: таблица способна переходить по горизонтали и вертикали, сохраняя структуру. Это особенно важно для ведомостей, где заранее неизвестно число строк и длина описания.
Перед заполнением полезно определить назначение каждой колонки: фиксированная ширина для кода и количества, гибкая — для описания, ограниченная — для цены и суммы. Если все колонки считать пропорциональными строке, длинное название может сжать числовые значения до переноса. Для финансовых таблиц числа выравнивают вправо, единицы измерения отделяют, а итоговые строки визуально связывают с соответствующими колонками.
Продолжение таблицы требует контроля повторяемого заголовка и признака переполнения. Типовой алгоритм создаёт таблицу в доступной области, добавляет строки, проверяет продолжение, затем переносит оставшуюся часть на новую страницу. Вложенные элементы могут увеличить высоту строки, поэтому оценка по числу записей ненадёжна; нужно опираться на фактическую геометрию, возвращаемую элементом.
Списки поддерживают продолжение, смешивание нумерованных и маркированных уровней и глубокую вложенность. Для регламентов и инструкций это удобнее ручной расстановки маркеров: перенос строки не ломает отступ и номер. Однако чрезмерная вложенность быстро съедает ширину страницы, поэтому после третьего уровня лучше пересмотреть структуру или использовать таблицу терминов.
Штрихкоды и диаграммы
Штрихкоды создаются как векторные элементы и не требуют специального шрифтового файла. Доступны QR Code, Data Matrix, PDF417, Aztec, Code 128, Code 39, EAN, UPC, ISBN, GS1 и почтовые варианты. Векторное построение сохраняет чёткие границы при печати, но не отменяет требований стандарта к тихой зоне, размеру модуля, контрольной цифре и допустимому набору символов.
Для проверки штрихкода недостаточно увидеть его на экране. Нужно распечатать документ на целевом масштабе, отсканировать несколькими устройствами и убедиться, что просмотрщик не применяет подгонку к странице. Неправильный размер модуля, слишком низкий контраст, цветной фон и сжатие изображения — типичные причины отказа считывания. Непропорциональное изменение ширины и высоты для линейных кодов особенно опасно.
Диаграммы строятся как векторные объекты; доступны area, bar, column, line, pie и scatter. Они подходят для отчётов, где данные уже подготовлены приложением и требуется стабильная печатная графика. Сложную интерактивность, анимацию и пользовательские плагины ожидать не следует. Перед добавлением диаграммы полезно сократить число категорий, подписать единицы и предусмотреть чёрно-белую печать.
Если диаграмма или штрихкод зависят от данных, проверяют пустой набор, отрицательные значения и переполнение подписей. Хороший макет не падает при отсутствии точек, а выводит понятную служебную строку или скрывает блок по условию. Это проще реализовать на уровне подготовки модели и условий DLEX, чем ловить исключение в самом конце генерации.
Объединение, импорт и изменение существующих PDF
Core Suite объединяет документы, добавляет страницы к создаваемому файлу и импортирует отдельные страницы. Вход можно читать из файла, Stream или byte array. При построении пакета документов удобно хранить порядок как список источников и диапазонов страниц, а не создавать промежуточные PDF после каждого шага. Один проход уменьшает количество операций ввода-вывода и упрощает обработку ошибки конкретного источника.
Импортированную страницу можно масштабировать, поворачивать и обрезать, а также размещать несколько страниц на одном листе. Это основа для буклетов, раздаточных материалов и превью. При N-up размещении следует учитывать не только прямоугольник страницы, но и её Rotate, CropBox и MediaBox; иначе часть содержимого окажется за границей или повернётся дважды.
Настройки слияния управляют аннотациями, слоями, тегами, закладками, полями форм и JavaScript. Сохранение всего без разбора не всегда правильно. Например, документы с одинаковыми именами полей могут образовать связанные AcroForm-поля, а сценарии из внешнего файла могут быть нежелательны. Для входящих документов безопаснее сформулировать политику: что сохранять, что удалять и какие типы содержимого запрещать.
Линеаризация создаёт структуру Fast Web View, позволяющую начать показ документа до полной загрузки. Она полезна для больших файлов, отдаваемых по сети, но не исправляет тяжёлые изображения и не заменяет оптимизацию. После любых изменений линеаризацию выполняют на финальном документе, потому что последующая правка может нарушить рассчитанную структуру.
Формы AcroForm и XFA
При чтении AcroForm можно получать значения, координаты и часть оформления полей, реорганизовывать поля при слиянии и проверять JavaScript-действия. Полный набор функций позволяет заполнять, изменять оформление, создавать appearance stream, удалять или выравнивать отдельные поля и превращать форму в обычное содержимое. Flatten нужен, когда интерактивность больше не требуется и значения должны выглядеть одинаково у получателя.
Заполнение формы состоит не только в присвоении Value. Просмотрщик показывает appearance stream, и если он не обновлён, визуальное состояние может расходиться со значением, которое извлекает программа. После заполнения проверяют, сформировано ли представление, корректно ли встроен шрифт и не выходит ли текст за прямоугольник. Для checkbox и radio button важно использовать допустимые export values, а не произвольные слова.
При слиянии форм возможны конфликты имён. Два поля с одинаковым именем могут начать отображать одно значение, хотя в исходниках были независимыми. Решение — переименовать поля, разделить формы или flatten перед объединением, если редактирование после сборки не требуется. Выбор зависит от того, должен ли получатель продолжать ввод данных.
Статические XFA-формы можно заполнять в поддерживаемых сценариях, но динамический XFA и сложные вычисления требуют отдельной проверки. Такие документы часто зависят от конкретного просмотрщика, поэтому тестирование только в одном приложении недостаточно. Если задача допускает переход на AcroForm или обычный PDF, это обычно повышает предсказуемость архивации и просмотра.
Водяные знаки, штампы и слои
Текстовый или графический водяной знак добавляют как элемент страницы либо через шаблон, повторяемый на выбранных страницах. Для диагональной отметки задают угол, прозрачность, положение и размер. Слишком насыщенный знак ухудшает чтение, а слишком светлый пропадает при чёрно-белой печати; оптимальный вариант проверяют на мониторе и бумаге.
Штамп отличается от обычного фона назначением: он содержит статус, дату, идентификатор операции или сведения о подписанте и обычно наносится поверх исходного документа. При пакетной обработке стоит сохранять источник этих значений в журнале, чтобы позднее объяснить происхождение отметки. Если штамп критичен юридически, одного графического изображения недостаточно — нужна цифровая подпись или иная проверяемая защита.
Дополнительные слои PDF могут сохраняться при слиянии. Это полезно для чертежей и вариантов представления, но увеличивает сложность проверки: просмотрщик может скрывать слой по умолчанию. При выпуске финальной копии для архива иногда разумнее зафиксировать видимое состояние, если бизнес-процесс не требует переключаемых слоёв.
Защита, шифрование и цифровые подписи
Поддерживаются пользовательский и владельческий пароли, разрешения, RC4, AES-128 и AES-256. Для новых систем выбирают AES-256, если его поддерживают целевые просмотрщики и политика организации. Пароль пользователя ограничивает открытие, а пароль владельца и permissions задают разрешённые действия; сами разрешения не следует считать абсолютной защитой от злонамеренного инструмента, поскольку они рассчитаны на корректное поведение программ чтения.
Цифровая подпись создаётся на основе сертификата из файла или хранилища и может быть видимой либо невидимой. В документе можно подписывать несколько полей, использовать инкрементальные обновления, внешних провайдеров и профили PAdES. Для долгосрочной проверки важны цепочка сертификатов, метка времени и сведения об отзыве; простое наличие рисунка подписи не подтверждает целостность.
Подписание выполняют после всех операций, изменяющих байты документа. Добавление страницы, метаданных или водяного знака после подписи может сделать её недействительной либо обозначить документ как изменённый после подписания. Несколько подписей добавляют инкрементально в заранее предусмотренные поля, сохраняя предыдущие ревизии.
При работе с облачным или аппаратным ключом приватный ключ не должен покидать провайдера. Приложение формирует дайджест, передаёт его на подпись и помещает результат в PDF. Такой процесс требует точного соблюдения размера зарезервированного контейнера и алгоритма; ошибки проявляются как недостаточная область подписи или неверная проверка. Логи должны содержать идентификатор сертификата и результат, но не секреты.
PDF/A, PDF/X и доступность
Для архивирования поддерживаются профили PDF/A-1, PDF/A-2 и PDF/A-3 с вариантами a, b и u, а для полиграфии — PDF/X-1a и PDF/X-3. Соответствие требует больше, чем установка одного флага: шрифты должны быть встроены, цветовые пространства описаны, запрещённые функции исключены, а метаданные и Output Intent согласованы. Внешний валидатор следует включить в контроль качества, особенно при массовом архивировании.
PDF/A-3 допускает вложенные файлы и подходит для связки визуального документа с исходными данными, но вложение нужно описать корректно и согласовать с профилем организации. PDF/X ориентирован на печатный процесс и требует аккуратного управления CMYK, spot colors и ICC-профилем. Экранный вид в обычном просмотрщике не гарантирует правильного цветоделения.
Логическая структура и PDF/UA помогают программам чтения определить заголовки, абзацы, таблицы, ссылки и порядок чтения. Элементам изображений задают альтернативное описание, декоративные элементы помечают как артефакты, а нумерацию страниц не включают в основной поток. Доступность нельзя получить одной автоматической настройкой: порядок добавления элементов, структура таблиц и смысловые подписи требуют проектирования.
При импорте тегированных PDF структура может сохраняться, однако добавленное поверх содержимое нужно тегировать отдельно. Слияние нескольких документов с разными деревьями структуры требует проверки итогового порядка. Практический тест включает не только валидатор, но и чтение клавиатурой и экранным диктором, потому что формально допустимый порядок может быть неудобным.
Метаданные, закладки и навигация
Document хранит заголовок, автора, тему, ключевые слова и другие свойства, а XMP позволяет читать и обновлять расширенные метаданные. Значения должны описывать итоговый файл, а не шаблон или техническое имя сервиса. При объединении нескольких источников выбирают явную политику: сохранить метаданные главного документа, сформировать новые или объединить отдельные поля.
Закладки и outlines улучшают навигацию по длинному отчёту. Можно создавать и перестраивать дерево, задавать стиль и цвет, связывать элементы с координатой или масштабом страницы. Автоматическая генерация закладок по секциям полезна, если названия стабильны и не содержат пустых значений. После удаления или перестановки страниц назначения нужно проверить, чтобы они не указывали на старые позиции.
Ссылки и действия включают переход по документу, открытие файла, URL, импорт и отправку данных, показ и скрытие аннотаций, сброс формы и JavaScript. Для документов, поступивших извне, активные действия следует рассматривать как потенциально нежелательные. Перед публикацией можно обнаружить JavaScript и удалить или заблокировать его по политике безопасности.
Извлечение текста, изображений и вложений
Полный набор функций извлекает текст из страницы, документа или ограниченной области. Область полезна для форм фиксированного вида, где нужное значение расположено в известном прямоугольнике. Однако PDF хранит команды рисования, а не обязательную текстовую модель, поэтому порядок извлечения может отличаться от визуального. Для колонок, таблиц и раздельно нарисованных символов нужен постпроцессинг.
Текст нельзя извлечь из сканированного изображения без OCR. Core Suite может получить изображение или страницу, но распознавание следует поручить OCR-компоненту. Перед распознаванием полезно определить, есть ли уже текстовый слой: повторный OCR ухудшит качество поиска и может создать дублирующиеся строки.
Извлечение изображений, вложений и 3D-ресурсов удобно для аудита входящего документа. Имена вложений нужно нормализовать, запрещать выход за целевой каталог и проверять расширение по сигнатуре, а не доверять имени. Изображение также может быть маской, частью композиции или фрагментом страницы, поэтому извлечь фотографии не всегда означает получить готовые визуальные объекты.
Для пакетной индексации полезно сохранять номер страницы, координаты области и исходный идентификатор вместе с текстом. Тогда поиск может показать пользователю контекст, а служба поддержки — воспроизвести результат. Исключения парсинга следует связывать с хэшем входного файла, не сохраняя конфиденциальный документ в обычном журнале.
Отчёты и выражения DLEX
RecordBox и RecordArea могут выводить поле или вычисляемое выражение. Доступны арифметические, строковые, статистические, финансовые и агрегатные функции, включая агрегаты уровня страницы. Это позволяет вычислять строковую сумму, итоги, количество и условные подписи в макете. Сложную бизнес-логику всё же лучше готовить в модели, чтобы её можно было тестировать без рендеринга PDF.
Для счета типичный Detail содержит количество, описание, цену и выражение количества на цену. Footer показывает сумму, а ConditionalFooter — итог только на последней странице. NoSplitZone удерживает связанные элементы вместе, PageBreak создаёт жёсткий переход, SoftBreak предлагает предпочтительное место разрыва. Эти инструменты нужно применять осознанно: слишком большая зона без разрыва может не поместиться даже на пустой странице.
Subreport подходит для вложенных коллекций: заказ с позициями, клиент с договорами, подразделение с сотрудниками. Рекурсивные подотчёты позволяют строить иерархию, но увеличивают риск длинной верстки и циклических данных. На уровне модели следует ограничить глубину, а в тестах включить максимальную допустимую структуру.
Событийная модель отчёта позволяет реагировать на этапы разметки и подставлять дополнительные элементы. Её используют, когда выражений недостаточно, но код обработчика должен оставаться детерминированным. Доступ к сети или базе из события верстки создаёт непредсказуемое число вызовов; данные лучше загрузить заранее и передать в Layout одним набором.
Предварительный просмотр и контроль макета
Run Report соединяет текущий DLEX и тестовые данные, затем открывает сгенерированный PDF. Проверять следует не только первую страницу: важны переходы, повтор Header и Footer, последняя страница, пустой набор и длинные значения. Для шаблонов на готовом бланке сравнивают линии и поля при масштабе 100 процентов, потому что уменьшенный просмотр скрывает смещение на несколько пунктов.

Настройка привязки к сетке ускоряет выравнивание, но не заменяет точных размеров. Сетка удобна для чернового расположения, затем координаты и ширины проверяют в Properties. Placeholder помогает увидеть места, которые позже заполнит LayoutData, однако его поведение относится к соответствующему сценарию Core Suite и не должно приниматься за реальное значение данных.
Для регрессионной проверки можно сохранять контрольный PDF и сравнивать не только байты, которые меняются из-за метаданных, но и визуальный рендер страниц. Изменение шрифта, версии ОС или набора данных способно сдвинуть перенос на страницу. Хороший тест фиксирует допустимое отклонение и отдельно проверяет текстовые контрольные значения.
Производительность и память
Потребление памяти зависит от числа страниц, изображений, шрифтов, импортируемых ресурсов и выбранного способа вывода. Передача результата как большого массива байтов создаёт непрерывный блок памяти; поток уменьшает пиковую нагрузку. Для входных файлов также предпочтителен Stream, если источник уже доступен как поток, но поток должен оставаться открытым столько, сколько требуется операции.
Disk buffering помогает при больших слияниях, перенося часть работы из оперативной памяти во временное хранилище. Для сервера нужно выделить быстрый каталог с достаточным местом и настроить очистку после сбоев. Медленный сетевой диск может устранить OutOfMemoryException, но резко увеличить время, поэтому выбор проверяют нагрузочным тестом на реальном размере документов.
Повторное использование шрифтов и ресурсов сокращает объём. Если один и тот же шрифт добавляется как разные экземпляры с отличающимися именами или настройками, файл может содержать несколько подмножеств. Автоматическое sharing помогает, но наибольший эффект даёт единый реестр шрифтов и шаблонов в приложении.
Параллельная генерация требует изоляции изменяемых объектов. Не следует делить один Document, Page, Stream или экземпляр шаблона между запросами без явной гарантии потокобезопасности. Общими могут быть неизменяемые байты ресурса и настройки, а каждый документ создаётся внутри своего задания. Нагрузочный тест должен измерять не только среднее время, но и 95-й процентиль, сборку мусора и количество временных файлов.
Вывод из ASP.NET Core и фоновых служб
В веб-обработчике PDF удобно писать в MemoryStream и возвращать как файл с корректным Content-Type и безопасным именем. Для очень большого ответа лучше потоковая передача, чтобы не держать всю копию в памяти. Заголовок Content-Disposition выбирают по сценарию: inline для просмотра или attachment для явной загрузки. Имя не должно содержать управляющих символов и данных пользователя без очистки.
При отмене запроса генерация не всегда прекращается автоматически. Если отчёт долгий, токен отмены следует проверять между подготовительными этапами, а тяжёлую работу переносить в очередь. Клиент получает идентификатор задания, а готовый файл хранится ограниченное время. Это предотвращает повторный запуск одной и той же генерации из-за обновления страницы.
В фоновой службе важно атомарно публиковать результат: сначала записать во временный файл, затем переместить в конечное имя. Иначе другой процесс может прочитать незавершённый PDF. Имя временного файла делают уникальным, а каталог защищают от исполнения вложений и произвольного чтения.
Ошибки входного PDF, шрифта и лицензии следует различать. Пользователю возвращают понятный код задания, а журнал содержит этап, тип операции, размер источника, хэш и исключение. Пароли, ключи и содержимое полей формы в журнал не записывают. Для повторяемой ошибки сохраняют обезличенный минимальный пример, если политика данных это разрешает.
Типовые практические сценарии
Счёт с переменным числом позиций
Фирменный бланк подключают как PDF-шаблон, реквизиты заказа выводят в Header, позиции — в Detail, итоги — в ConditionalFooter. Описание размещают в RecordArea с переносом, числовые колонки выравнивают вправо, а NoSplitZone удерживает итоговые строки. После Layout к документу добавляют условия оплаты, приложения и при необходимости цифровую подпись.
Пакет документов клиента
Список источников содержит титульный лист, договор, приложения и вложенные подтверждения. Для каждого файла заранее проверяют пароль и диапазон страниц. При слиянии сохраняют нужные закладки, удаляют нежелательные действия и разрешают конфликт имён полей. В конце формируют единое дерево навигации, метаданные и линеаризацию.
Персональные сертификаты
Фиксированная Page использует фон, имя, дату, номер и QR-код. Длинное имя проходит проверку ширины и при необходимости получает меньший размер шрифта в допустимом диапазоне. QR-код кодирует идентификатор, а не чувствительные сведения. Итог подписывается сертификатом организации и сохраняется в PDF/A, если это предусмотрено архивной политикой.
Заполнение входящей анкеты
Система открывает AcroForm, сопоставляет имена полей с моделью, устанавливает значения и обновляет appearance stream. Поля, которые не должны изменяться получателем, flatten отдельно; остальные сохраняют интерактивность. Перед выдачей проверяют JavaScript, вложения и итоговые разрешения.
Извлечение зоны из унифицированного бланка
Для известного шаблона задают прямоугольник страницы и извлекают текст только из него. Результат нормализуют, сопоставляют с регулярным правилом и сохраняют вместе с координатами. Если текстового слоя нет, страницу отправляют на OCR; исходный PDF остаётся неизменным для аудита.
Ограничения, которые важно учитывать
Core Suite не предоставляет готовое пользовательское окно для свободного редактирования любого PDF. Designer проектирует DLEX-отчёты и фиксированные макеты, но не заменяет редактор, где сотрудник мышью исправляет абзац в произвольном существующем документе. Для такого процесса нужен отдельный редактор или специально разработанный интерфейс поверх API.
Отправка PDF на принтер относится к отдельному PrintManager. Генерация файла и программная печать — разные задачи: у них различаются драйверы, очереди, права службы и обработка диалогов. Если система должна печатать без участия пользователя, этот компонент и целевое окружение планируют отдельно.
Набор доступных классов зависит от лицензии. Базовые операции создания и слияния покрываются шире, а визуальные отчёты, расширенное извлечение, формы, изображения, штрихкоды, стандарты и подписи могут требовать полного набора. Перед архитектурным решением полезно составить таблицу реально используемых функций и проверить их статус в лицензии, а не ориентироваться на общее название продукта.
HTML-элементы поддерживают определённую разметку, но не воспроизводят весь современный браузерный стек. Для сложной веб-страницы с JavaScript, Grid и внешними стилями нужен специализированный HTML-рендерер. В Core Suite надёжнее строить документ из PageElements или DLEX, когда требуется точная геометрия и предсказуемая печать.
Диагностика ошибок и способы устранения
| Симптом | Вероятная причина | Что проверить |
|---|---|---|
| В PDF появилась демонстрационная отметка | Ключ не добавлен или функция не покрыта | Вызов AddLicense до Draw и состав лицензии |
| Кириллица заменена квадратами | Шрифт не содержит глифы или не встроен | Файл OpenType/TrueType, путь и режим embedding |
| Поле DLEX пустое | dataName не совпадает с моделью | JSON в Layout Data Editor и имя в Properties |
| Строка таблицы обрезана | Недостаточная высота или запрет продолжения | Overflow, continuation и размер ячейки |
| Итог повторяется на каждой странице | Он помещён в обычный Footer | ConditionalFooter или отдельная финальная секция |
| После слияния поля связались | Совпали имена AcroForm | Переименование, flatten или политика merge |
| Подпись недействительна | Документ изменён после подписания | Порядок операций и инкрементальные ревизии |
| Большое слияние завершается по памяти | Ресурсы держатся в RAM | Потоки, disk buffering, размеры изображений |
| Штрихкод не читается | Нарушены модуль, масштаб или тихая зона | Печать 100 процентов и тест сканером |
| Импортированная страница повернулась дважды | Не учтён Rotate исходника | Ориентация, MediaBox и преобразование |
| PDF/A не проходит валидатор | Невстроенный шрифт или неверный цветовой профиль | Embedding, ICC, XMP и выбранный профиль |
| Логотип размыт на бумаге | Низкое эффективное dpi | Пиксели исходника и масштаб в пунктах |
| Run Report не строит документ | Нет валидных данных или ошибка DLEX | JSON, Source View, id и выражения |
| Текст извлекается в странном порядке | Команды рисования не отражают чтение | Visible order, область и постобработка |
| На сервере не найден шаблон | Относительный путь рассчитан от другой папки | Content root, права и публикацию ресурса |
Начинать диагностику лучше с минимального воспроизводимого документа: одна входная страница, один элемент, один шрифт и вывод в файл. Если этот вариант работает, компоненты возвращают по одному. Такой подход быстрее, чем менять сразу лицензию, формат страницы и поток. Для ошибки парсинга полезно проверить тот же вход в другом просмотрщике и сохранить его хэш, потому что файл с одинаковым именем может отличаться содержимым.
При исключениях во время слияния следует обновить пакет до исправленной сборки, поскольку заметная часть выпусков содержит поддержку некорректных XRef, ColorSpace, AcroForm и аннотаций. Однако обновление не отменяет валидацию входа. Повреждённый PDF может открываться в tolerant-просмотрщике и всё равно нарушать структуру; такой файл стоит изолировать и при необходимости пересохранить доверенным процессом.
Сравнение DynamicPDF Core Suite с аналогами
| Программа | Лучше подходит для | Главное ограничение |
|---|---|---|
| DynamicPDF Core Suite | Создание, слияние, формы и DLEX-отчёты в .NET | Печать и полный набор функций требуют отдельных лицензируемых возможностей |
| iText для .NET | Низкоуровневая работа с PDF, подписи, стандарты и корпоративные процессы | Коммерческое применение требует внимательного соблюдения AGPL или покупки лицензии |
| Aspose.PDF for .NET | Широкая конвертация, редактирование и обработка множества форматов | Большой API и коммерческая лицензия усложняют лёгкий точечный сценарий |
| Syncfusion PDF Library | Проекты, уже использующие экосистему Syncfusion и её компоненты | Лицензионные условия и доступность функций нужно сверять с выбранным планом |
| PDFsharp и MigraDoc | Бесплатное создание документов и базовое объединение в .NET | Меньше готовых средств для форм, стандартов, подписей и сложного извлечения |
DynamicPDF удобнее выбирать, когда в одном проекте нужны объектная генерация, обработка существующих PDF и отчёты по визуальному DLEX-макету. iText подходит команде, которой важен глубокий контроль PDF и приемлема его модель лицензирования. Aspose.PDF разумен при широкой конвертации и большом наборе операций, Syncfusion — внутри уже принятой экосистемы компонентов, а PDFsharp с MigraDoc — для более простого открытого решения без полного набора корпоративных функций.
Как организовать проект, чтобы макеты не ломались
DLEX, шрифты, PDF-шаблоны, изображения и тестовые данные следует версионировать вместе. Изменение макета получает отдельный номер или хэш, который записывается в журнал генерации. Тогда можно точно восстановить, какой шаблон создал конкретный документ. Хранение единственного изменяемого файла без истории затрудняет разбор спора и воспроизводимость.
Контракт данных оформляют как отдельную модель и набор тестов. Обязательные поля проверяются до Layout, пустые коллекции получают определённое поведение, а строки нормализуются по длине. Для каждого макета полезны как минимум четыре набора: обычный, длинный, пустой и многостраничный. Тест генерирует PDF, проверяет число страниц и контрольные значения.
Ресурсы не должны зависеть от рабочего каталога процесса. В ASP.NET Core путь строят от ContentRootPath, в контейнере ресурсы копируют в образ, а в функции — упаковывают или получают из доверенного хранилища. Права выдаются только на чтение, кроме отдельного каталога временных файлов. Пользовательский путь никогда не объединяют с каталогом шаблонов без нормализации.
Секреты отделяют от макета. Пароли входных PDF, лицензионный ключ и ключи подписи хранятся в секретном хранилище, а DLEX содержит только структуру. В тестовых JSON не используют реальные персональные данные. Перед передачей макета дизайнеру значения заменяют синтетическими, сохраняя длину и тип, чтобы верстка оставалась реалистичной.
Контроль качества готового PDF
Проверка начинается с открытия файла минимум в двух независимых просмотрщиках. Сравнивают число страниц, ориентацию, шрифты, изображения, поля формы, закладки и подписи. Для печатного документа выполняют пробную печать без масштабирования и с типичными настройками офиса. Для мобильного сценария проверяют скорость первой страницы и удобство навигации.
Автоматический контроль может искать обязательный текст, проверять метаданные, отсутствие нежелательных действий, профиль PDF/A, валидность подписи и размер файла. Для водяных знаков и сложного макета добавляют визуальное сравнение рендеров. Допустимый порог должен учитывать сглаживание, но выявлять смещение строк и пропавшие элементы.
Конфиденциальные документы проходят отдельную проверку: отсутствие лишних вложений, старых ревизий, скрытых полей и метаданных шаблона. Flatten формы не гарантирует удаление исходного значения из всех структур, если обработка выполнена неверно; итог следует анализировать средствами извлечения. Перед публикацией внешнему получателю полезна политика санитарной обработки.
Размер файла оценивают относительно содержимого. Сотни мегабайт для короткого отчёта обычно указывают на изображения без уменьшения, повторное встраивание шрифтов или вложенный исходник. Оптимизация должна сохранять читаемость и стандарт соответствия; нельзя уменьшать качество подписи, штрихкода или скана с мелким текстом только ради целевого размера.
Рекомендации по выбору подхода внутри Core Suite
- Используйте PageElements, когда геометрия документа задаётся кодом и требуется максимальный контроль над каждой страницей.
- Используйте DLEX и DocumentLayout, когда макет должен настраиваться визуально и заполняться повторяющимися данными.
- Импортируйте готовую страницу, когда внешний бланк уже утверждён и поверх него нужно нанести значения.
- Применяйте merge для сборки пакета из целых документов и заранее определяйте политику форм, закладок и действий.
- Flatten выполняйте только после решения, какие поля получатель должен продолжать редактировать.
- Подписывайте документ последней операцией и используйте метку времени, если важна долгосрочная проверка.
- Выводите большие результаты в поток и включайте disk buffering после нагрузочного измерения, а не по умолчанию.
- Проверяйте лицензионное покрытие конкретных классов до реализации, чтобы архитектура не зависела от недоступной функции.
Дополнительные проверки перед внедрением
До первого промышленного запуска полезно провести инвентаризацию всех типов входных документов. В выборку включают обычный PDF, защищённый файл, документ с формой, файл со слоями, тегированный PDF, скан, документ с большим изображением и намеренно повреждённый пример. Для каждого фиксируют ожидаемую операцию и допустимое поведение при отказе. Такая матрица показывает, где библиотека должна продолжить обработку, где запросить пароль, а где изолировать источник.
Отдельно проверяют культуру и часовой пояс. Дата в отчёте может формироваться сервером в UTC, а пользователь ожидает местное время; десятичный разделитель и порядок дня с месяцем также зависят от культуры. Формат нужно задавать явно в модели или выражении, а не полагаться на настройки машины. Для финансового документа округление выполняют до передачи в макет по принятому бизнес-правилу.
Стабильность шрифтов контролируют хэшем файлов. Обновление шрифта с тем же именем способно изменить метрики и переносы, поэтому набор шрифтов поставляют вместе с приложением, если это разрешено лицензией, и обновляют осознанно. На Linux нельзя рассчитывать на наличие тех же системных гарнитур, что на компьютере разработчика. Подмена гарнитуры должна быть явной и протестированной.
Для цифровой подписи заранее проверяют срок действия сертификата, цепочку доверия, доступ к службе меток времени и поведению при недоступности сети. Процесс должен различать временный сетевой сбой и окончательно недействительный сертификат. Повтор операции не должен создавать несколько незавершённых полей или публиковать неподписанный файл под именем окончательного.
Нагрузочный профиль строят на реальных размерах: число страниц, средний вес изображения, количество одновременных запросов и доля слияний. Маленький синтетический PDF почти ничего не говорит о пиковом потреблении памяти. Измерения проводят после прогрева, отдельно для холодного старта и стабильной работы, а результаты связывают с версией шаблона и набором ресурсов.
Политику обновления пакета оформляют так же строго, как для других серверных зависимостей. Новую сборку проверяют на контрольных PDF, особенно на подписях, формах, тегах и нестандартных входах. Исправление парсера может изменить обработку ранее проблемного файла; поэтому регрессия включает как успешные документы, так и примеры, которые должны корректно отклоняться.
Права файловой системы делают минимальными. Процессу генерации разрешают читать каталог шаблонов и писать только во временный и выходной каталоги. Имена входных и выходных файлов формируются приложением, а не принимаются напрямую. После завершения временный файл удаляется в блоке finally, а отдельная задача очищает остатки после аварийного завершения.
Если документ отправляется по электронной почте или через внешнюю систему, ограничение размера проверяют до публикации. При превышении порога процесс может оптимизировать изображения, разделить пакет или поместить файл в защищённое хранилище. Решение не должно молча ухудшать качество: выбранный вариант записывают в журнал и показывают оператору.
Для шаблонов с персональными данными полезна автоматическая проверка на остаточные тестовые значения. После генерации ищут слова-маркеры, использованные в макете, и запрещают выдачу, если они сохранились. Такой тест обнаруживает не только пустой dataName, но и случай, когда дизайнер оставил пример имени или номера непосредственно в Label.
Наконец, следует определить срок хранения созданных документов и исходных данных. Повторная генерация через несколько лет может дать иной результат из-за изменившегося шаблона, шрифта или правил. Для юридически значимых процессов сохраняют финальный подписанный PDF, идентификатор шаблона, хэши ресурсов и минимальный набор технических метаданных, позволяющий подтвердить происхождение файла.
Чек-лист приёмки макета
| Область | Критерий |
|---|---|
| Страница | Формат, ориентация и поля совпадают с утверждённым образцом. |
| Текст | Кириллица, цифры, знаки валют и смешанные направления отображаются выбранным шрифтом. |
| Данные | Все dataName существуют в контракте, пустые значения имеют ожидаемое представление. |
| Повторение | Header и Footer появляются на нужных страницах, а Detail не теряет записи. |
| Разрывы | NoSplitZone не превышает полезную высоту и не создаёт бесконечный перенос. |
| Таблицы | Заголовки повторяются, числовые колонки выровнены, длинная строка продолжается. |
| Формы | Значения и appearance совпадают, имена полей не конфликтуют после merge. |
| Изображения | Эффективное разрешение достаточно для печати, прозрачность и пропорции сохранены. |
| Штрихкоды | Код читается с бумажной копии при масштабе 100 процентов. |
| Навигация | Закладки ведут на правильные страницы после перестановки и добавления приложений. |
| Безопасность | Нежелательные действия, вложения и метаданные удалены согласно политике. |
| Стандарт | PDF/A или PDF/X проходит независимый валидатор и содержит нужный Output Intent. |
| Подпись | Все изменения завершены до подписания, метка времени и цепочка проверяются. |
| Производительность | Размер, время и память укладываются в пределы на максимальном наборе данных. |
| Публикация | Файл появляется атомарно, имя безопасно, временные ресурсы удаляются. |
Потоки, массивы байтов и освобождение ресурсов
Для веб-ответа или передачи в объектное хранилище документ удобнее формировать в Stream, а не сначала записывать на диск. Поток должен оставаться открытым до завершения Draw, потому что часть содержимого, таблиц, шрифтов и кросс-ссылок записывается при финализации. Если вызывающий код закрывает поток раньше, результат может иметь правильный заголовок PDF, но неполный каталог объектов и не открываться.
Массив байтов удобен для коротких документов и очередей сообщений, однако его размер полностью занимает управляемую память. Для многостраничного отчёта с фотографиями предпочтителен поток с дисковым буфером либо временный файл. Порог выбирают по измерениям: один и тот же макет может занимать мало места с векторной графикой и резко вырасти после добавления нескольких исходных JPEG или TIFF.
Входные потоки и объекты чтения следует освобождать после завершения импорта. Особенно это важно при пакетном merge, где десятки файлов остаются открытыми одновременно. Без явного жизненного цикла сервис быстро достигает лимита файловых дескрипторов или блокирует удаление источника. Ошибка одного файла не должна пропускать очистку остальных ресурсов, поэтому закрытие выполняют в finally или через конструкцию using.
Повторное использование одного изменяемого Document между параллельными запросами создаёт гонки: страницы, метаданные и элементы могут попасть не в тот результат. Каждый запрос получает собственный граф объектов, а общими оставляют только неизменяемые настройки и безопасный кэш ресурсов. Если шрифт или шаблон кэшируется, его поток не должен быть закрыт до окончания всех операций, которые от него зависят.
Порядок рисования, координаты и наложение элементов
Элементы страницы выводятся в порядке добавления: поздний объект способен перекрыть ранний. Это важно для подложки, водяного знака, изображения подписи и интерактивного поля. Фон добавляют первым, основной текст и таблицы — после него, а штамп поверх содержимого — в конце. Прозрачность не отменяет перекрытие; непрозрачная заливка RecordBox или Rectangle может скрыть уже нарисованный текст.
Координаты задаются относительно выбранной области страницы, поэтому поля и поворот нужно учитывать до расчёта позиции. На альбомной странице ширина и высота меняются местами, а импортированный лист может иметь собственный Rotate. Надёжный код получает полезную область из параметров страницы и размещает элементы относительно неё, а не использует числа, скопированные из другого формата бумаги.
Поворот текста и изображений следует проверять вместе с точкой привязки. После вращения визуальный прямоугольник выходит за исходные границы, поэтому объект у края страницы может обрезаться. Для диагонального штампа сначала рассчитывают центр, затем угол и размер, а не пытаются компенсировать обрезку случайным смещением.
Когда поверх импортированной страницы добавляются поля, координаты сверяют с фактическим CropBox. Бланк, созданный в графическом редакторе, может иметь MediaBox большего размера и смещённую область обрезки. В просмотрщике это незаметно, но значения окажутся сдвинутыми. Проверка прямоугольников страницы до нанесения данных устраняет такой класс ошибок.
Файловый проводник и управление ресурсами Designer
File Explorer в Designer помогает открывать DLEX, PDF-подложки и связанные ресурсы без выхода из рабочей области. При переносе макета на другой компьютер важны не только сами файлы, но и способ разрешения путей. Абсолютная ссылка на каталог разработчика почти наверняка сломается на сервере, поэтому ресурсы располагают в контролируемой структуре проекта и проверяют после публикации.

Имя ресурса лучше делать стабильным и не включать пользовательский ввод. Для нескольких брендов или языков создают явное сопоставление разрешённых файлов, а не строят путь из параметра запроса. Так макет сохраняет гибкость, но не превращается в точку доступа к произвольному файлу на сервере.
При замене фонового PDF нужно сравнить размеры страниц, поля и контрольные координаты. Даже визуально похожий бланк может иметь другую область обрезки, что сдвинет RecordBox и изображения. Автоматический тест генерирует документ с метками по углам и сравнивает их положение с эталоном до выпуска обновлённого шаблона.
Колонтитулы, нумерация и состояние секций
Header и Footer полезны не только для статического текста. В них размещают номер страницы, название отчёта, дату формирования и повторяемые линии таблицы. Высота секции уменьшает пространство Detail, поэтому слишком высокий колонтитул увеличивает число страниц и может вызвать неожиданное переполнение. Перед добавлением элементов следует зафиксировать его реальную высоту и отступы.

Нумерацию приложений иногда требуется начинать заново или выводить римскими цифрами. Для этого логическую метку страницы отделяют от физического индекса. Закладки и ссылки должны указывать на фактическую страницу, а отображаемый номер формируется по правилам документа. Простая подстановка общего счётчика не подходит, если титульный лист не нумеруется или разделы имеют собственные диапазоны.
Условный Header не следует имитировать пустыми строками: секция всё равно занимает место. Лучше управлять видимостью или использовать отдельный отчёт и шаблон для первой страницы, если макет существенно отличается. При многоуровневых данных проверяют, какой заголовок относится к странице, группе или вложенному отчёту, иначе название предыдущей группы может остаться над следующей.
Аннотации, действия и недоверенные входные PDF
Входящий PDF может содержать заметки, ссылки, файловые вложения, JavaScript и действия открытия. При merge они способны перейти в итоговый документ, хотя пользователь ожидает только видимое содержимое. Политику импорта задают явно: сохранить деловые комментарии, удалить исполняемые действия, проверить вложения и исключить ссылки на локальные пути.
Аннотация имеет прямоугольник, внешний вид и действие; удаление только видимого значка не всегда удаляет связанную логику. После санитарной обработки документ повторно анализируют на JavaScript, Launch actions и вложенные файлы. Для публичного архива разумно разрешать только те типы, которые нужны процессу, а остальные отклонять или превращать в статическое изображение после проверки.
Пароль не делает содержимое безопасным для обработки. После успешного открытия файл всё равно может быть огромным, повреждённым или содержать чрезмерно сложные ресурсы. Ограничивают размер входа, число страниц, время выполнения и объём временных данных. Сбой одного документа возвращает контролируемую ошибку и не оставляет частично опубликованный результат.
Имена вложений нормализуют и проверяют по сигнатуре. Расширение .pdf не гарантирует, что внутри PDF, а имя с последовательностями перехода к родительскому каталогу не должно влиять на путь сохранения. Извлечённый файл сначала помещают в карантин, вычисляют хэш и только затем передают следующему компоненту.
Работа в Linux, контейнере и службе без интерфейса
В контейнере чаще всего ломаются шрифты и пути к ресурсам, а не сам код генерации. Нужные гарнитуры добавляют в образ законным способом, после чего тестируют кириллицу, жирное начертание и символы валют. Наличие файла ещё не означает, что выбран правильный шрифт: подстановка может изменить ширину строки и число страниц.
Каталог шаблонов копируют на этапе сборки и открывают только для чтения. Временные файлы направляют в отдельный том с ограничением размера и регулярной очисткой. Если корневая файловая система неизменяема, попытка записать рядом с приложением завершится ошибкой доступа; путь вывода и disk buffering должны указывать на разрешённую область.
Часовой пояс, культура и локаль контейнера часто отличаются от рабочей станции. Даты, числа и сортировку формируют по явным правилам модели. Название месяца или десятичный разделитель не должны зависеть от базового образа. Визуальные тесты запускают на том же образе, который используется в эксплуатации, иначе расхождение шрифтов останется незамеченным.
Для горизонтального масштабирования каждый экземпляр должен создавать независимый временный файл и публиковать результат атомарно. Общее имя вроде report.pdf вызывает перезапись при одновременных запросах. Безопасная схема использует уникальный идентификатор, завершает запись, проверяет файл, затем одной операцией перемещает его в конечное хранилище.
Регрессионная проверка макета и содержимого
Побайтовое сравнение PDF редко подходит для регрессии: даты, идентификаторы и порядок служебных объектов могут меняться без визуальной разницы. Надёжнее сочетать несколько проверок: количество страниц, извлечённый контрольный текст, наличие полей и закладок, профиль стандарта, валидность подписи и растровое сравнение выбранных страниц.
Эталонные рендеры создают для крайних наборов данных, а различия оценивают с допуском на сглаживание. Маска исключений не должна скрывать области с бизнес-данными. Если изменился перенос строки, тест показывает конкретную страницу и прямоугольник, чтобы дизайнер мог отличить ожидаемое изменение от пропавшего элемента.
Тест формы проверяет не только значение поля, но и внешний вид после открытия в нескольких просмотрщиках. Для подписи проверяется криптографический статус, а не наличие видимого изображения. Для PDF/A фиксируют отчёт независимого валидатора. Такой набор проверок обнаруживает ошибки, которые обычное открытие файла не показывает.
После изменения DLEX тесты запускают до публикации ресурса. Макет и код модели данных выпускаются согласованно: новый dataName нельзя добавлять в шаблон раньше, чем сервис начнёт его предоставлять. При обратной совместимости поле получает безопасное значение по умолчанию, а удаление выполняют только после проверки всех используемых макетов.
Итоговый рабочий алгоритм
- Определить, создаётся ли документ с нуля, заполняет готовый бланк, объединяет файлы или строит отчёт.
- Зафиксировать размеры страниц, поля, требования к шрифтам, стандарту, формам и подписи.
- Подготовить модель данных и крайние тестовые наборы.
- Собрать PageElements либо DLEX-макет и проверить переходы на нескольких страницах.
- Подключить входные PDF и настроить сохранение аннотаций, полей, слоёв и действий.
- Добавить метаданные, навигацию, защиту и соответствие требуемому профилю.
- Сгенерировать в поток или временный файл, затем выполнить подпись и финальную линеаризацию.
- Провести автоматическую, визуальную и печатную проверку, после чего атомарно опубликовать результат.
DynamicPDF Core Suite раскрывается лучше всего там, где PDF является частью автоматизированного процесса: документ строится из проверенных данных, проходит предсказуемую верстку, дополняется формами или подписью и передаётся дальше без ручной правки. Надёжность достигается не количеством вызовов API, а дисциплиной вокруг макетов, шрифтов, входных файлов, лицензий и финальной проверки. При таком подходе одна объектная модель обслуживает короткие справки, многостраничные отчёты, пакеты договоров и архивные экземпляры, сохраняя управляемость каждого шага.