С iText Suite можно программно создавать PDF из данных и HTML, объединять и разбивать документы, изменять страницы, заполнять формы, добавлять подписи, защищать файлы, извлекать текст и изображения, выполнять безопасное удаление конфиденциальных фрагментов и распознавать сканы. Основные инструменты — объектная модель PDF, движок макета, средства форм и подписей, конвертер pdfHTML, а также компоненты pdfSweep, pdfOCR, pdfCalligraph, pdfOptimizer и pdfXFA — позволяют собрать воспроизводимый конвейер вместо ручной обработки.
Рабочий процесс строится вокруг проекта: разработчик подключает необходимые зависимости, открывает входной поток через PdfReader, направляет результат в PdfWriter и управляет содержимым через PdfDocument либо высокоуровневый Document. Параметры страницы, шрифты, поля, таблицы, изображения, метаданные и защита задаются в коде, а полученный файл сразу проверяется в обычном просмотрщике PDF и автоматическими тестами.
Типовая цепочка состоит из четырёх этапов: получить данные и ресурсы, сформировать или открыть документ, выполнить преобразования в строго заданном порядке и только затем закрыть объекты, чтобы записались таблица перекрёстных ссылок и завершающие структуры. Такой порядок важен при пакетной генерации счетов, конвертации HTML, заполнении анкет, нанесении штампов, удалении персональных данных и подписании, потому что некоторые операции требуют инкрементального сохранения, совместимых компонентов и заранее подготовленных шрифтов.
Скачать iText Suite
- Редактирование PDF
- Русский интерфейс
- Просто новичкам
- Нет визуального редактора
- Нужны навыки Java или C#
- AGPL требует раскрытия кода
Как устроен рабочий проект
В iText Suite нет единого окна с панелью инструментов: действия выражаются классами, методами и настройками внутри Java- или C#-проекта. Это меняет подход к задаче. Вместо открытия файла и последовательного нажатия кнопок разработчик описывает процедуру, которую можно повторить для одного документа, тысячи файлов или запроса из корпоративной системы. Входом служит путь, поток байтов или массив, а выходом — файл, поток ответа, объектное хранилище либо следующий этап обработки.
Минимальная схема для нового документа включает PdfWriter и PdfDocument, а для удобной верстки поверх них создаётся Document. PdfDocument отвечает за низкоуровневую структуру PDF: страницы, каталоги, объекты, вложения, метаданные, формы и аннотации. Document отвечает за потоковый макет: абзацы, таблицы, списки, изображения и автоматический перенос между страницами. Если задача состоит только в копировании страниц или чтении объектов, высокоуровневый слой можно не создавать.
При изменении существующего файла одновременно используются PdfReader и PdfWriter. Нельзя записывать результат поверх входного файла тем же открытым потоком: безопаснее направлять вывод во временное имя, успешно закрывать документ, проверять результат и лишь затем заменять исходный объект. Такой шаблон защищает от потери данных при исключении, нехватке места или повреждённом входном PDF. Для обработки в памяти применяются ByteArrayOutputStream в Java либо MemoryStream в C#, но большие документы лучше передавать потоками, чтобы не создавать несколько полных копий в оперативной памяти.
Закрытие объектов является частью формата, а не формальностью. Метод close завершает незаписанные страницы, освобождает шрифты, строит таблицу перекрёстных ссылок и записывает трейлер. Если приложение возвращает массив байтов до закрытия Document или PdfDocument, файл может оказаться пустым либо неполным. Удобный способ избежать ошибки — конструкции try-with-resources в Java и using в C#, причём закрывать следует внешний объект Document: он передаст закрытие PdfDocument и PdfWriter.
Минимальная генерация документа
try (PdfWriter writer = new PdfWriter(output);
PdfDocument pdf = new PdfDocument(writer);
Document document = new Document(pdf)) {
document.setMargins(36, 42, 48, 42);
document.add(new Paragraph("Счёт № 1048")
.setFontSize(18)
.setBold());
document.add(new Paragraph("Документ сформирован из данных заказа."));
}
Этот фрагмент показывает полезное разделение ответственности: Writer управляет записью, PdfDocument — PDF-объектами, Document — размещением элементов. В производственном коде к нему добавляют обработку исключений, журналирование идентификатора задания, ограничение размера входных ресурсов и атомарную публикацию результата. Для повторяемой верстки параметры полей, шрифтов и цветов лучше вынести в фабрику стилей, а не задавать в каждом абзаце.
Создание страниц и управление геометрией
Размер страницы задаётся объектом PageSize; доступны стандартные форматы и произвольные прямоугольники в пунктах, где 72 пункта соответствуют одному дюйму. Ориентация меняется не флагом отображения, а выбором ширины и высоты, например PageSize.A4.rotate(). Для документов с разными листами новую страницу можно добавить с отдельным PageSize, а затем продолжить вывод через AreaBreak. Это полезно, когда основная часть отчёта печатается на A4, а широкая сводная таблица — на альбомном листе.
У PDF есть несколько рамок страницы. MediaBox задаёт физический носитель, CropBox — видимую область, TrimBox и BleedBox применяются в полиграфии, ArtBox описывает художественную область. При добавлении штампов или вычислении координат нельзя без проверки считать, что начало видимой области находится в точке 0,0: импортированный документ может иметь смещённый CropBox или поворот. Надёжный алгоритм получает фактический размер страницы и преобразует координаты с учётом rotation, а не использует постоянные значения A4.
Высокоуровневый макет автоматически создаёт страницы, когда текущая область заполнена. Поведение регулируют поля Document, отступы элементов, KeepTogether, KeepWithNext и пользовательские рендереры. Для заголовка раздела обычно задают KeepWithNext, чтобы он не оставался последней строкой страницы. Для короткой таблицы можно включить KeepTogether, но для длинной это приведёт к повторным попыткам разместить неделимый блок и предупреждениям о переполнении. В таком случае разрешают разрыв и настраивают повтор заголовочных строк.
Динамические колонтитулы удобно рисовать обработчиком события завершения страницы. Обработчик получает PdfPage, размер листа и PdfCanvas, поэтому может вывести номер, название документа, линию, штрихкод или фоновую метку. Важно резервировать место полями: графика, нарисованная прямо на canvas, не участвует в расчёте потока и способна перекрыть основной текст. Номер общего количества страниц часто требует второго прохода либо шаблонного XObject, который заполняется после завершения содержимого.
Текст, шрифты и символы
Надёжный PDF должен не только визуально показывать буквы, но и хранить корректное соответствие глифов Unicode. Для кириллицы, греческого, арабского, иврита и азиатских письменностей следует подключать TTF, OTF или коллекции TTC с нужным набором знаков. Встроенные базовые шрифты PDF не подходят для универсального документа: они ограничены кодировками и не гарантируют одинаковое отображение на всех устройствах. FontProgramFactory и PdfFontFactory позволяют загрузить файл шрифта, выбрать кодировку Identity-H и включить внедрение.
Если в тексте встречается знак, которого нет в выбранном шрифте, результатом может стать пустой квадрат, пропуск или исключение. Проверку лучше выполнять до выпуска документа: сформировать набор уникальных символов из данных, сопоставить его с доступными глифами и настроить последовательность замены. FontProvider в pdfHTML и механизмах макета способен искать подходящий шрифт среди зарегистрированных семейств, но качество зависит от того, какие файлы действительно переданы приложению. Название семейства в CSS само по себе не добавляет шрифт.
Внедрение делает файл переносимым, но увеличивает размер. Подмножество шрифта содержит только использованные глифы и обычно является разумным выбором для отчётов и счетов. Полное внедрение требуется, если документ позднее будет дополняться тем же шрифтом или правила конкретного стандарта требуют сохранения всей программы шрифта. При объединении сотен документов одинаковые подмножества могут дублироваться; для такой задачи полезны умное копирование объектов и последующая оптимизация.
Жирность и курсив нельзя достоверно получить простым указанием свойства, если соответствующего начертания нет. Искусственное утолщение или наклон ухудшают качество и могут не соответствовать фирменному стилю. Лучше зарегистрировать обычный, полужирный, курсивный и полужирный курсивный файлы как одно семейство. Это особенно заметно в HTML-конвертации, где CSS font-weight: 600 или 700 должен быть сопоставлен с реальным начертанием.
Форматы WOFF и WOFF2 распространены в веб-шаблонах. Конвертер способен работать с поддерживаемыми веб-шрифтами, но на сервере часто надёжнее держать лицензированные TTF или OTF рядом с шаблоном и явно регистрировать их. Это устраняет зависимость от сетевой загрузки, заголовков доступа и изменяющихся файлов на внешнем ресурсе. Перед внедрением следует проверить лицензию шрифта: техническая возможность не означает разрешения распространять его внутри PDF.
Сложные письменности
Для арабского, деванагари, бенгальского, тайского и других письменностей недостаточно вывести Unicode-коды по порядку. Нужны формирование лигатур, позиционирование глифов, изменение формы буквы в зависимости от соседей и двунаправленный алгоритм. pdfCalligraph подключает необходимую обработку к макетному движку. Без неё символы могут выглядеть раздельными, располагаться в неверном порядке или иметь неправильные диакритические знаки.
В многоязычном документе полезно разделять абзацы по языку и направлению, а не полагаться на один универсальный стиль. Для правостороннего текста задаются направление письма и выравнивание, для смешанных строк проверяются номера, скобки и знаки пунктуации. Автоматические тесты должны извлекать текст и сравнивать его логический порядок, а визуальный тест — форму слов. Один лишь просмотр в конкретной программе не выявляет проблемы копирования и поиска.
Абзацы, таблицы и составная верстка
Paragraph поддерживает фрагменты Text с разными стилями, межстрочный интервал, отступ первой строки, интервалы до и после, выравнивание и переносы. В длинных документах лучше создавать именованные стили: основной текст, заголовок, примечание, сумма, код и предупреждение. Тогда изменение размера или шрифта выполняется в одном месте, а код формирования данных остаётся читаемым. Прямое форматирование каждого элемента быстро приводит к расхождениям между разделами.
Table принимает фиксированную либо относительную ширину столбцов. Для счёта удобно задавать массив пропорций, например 4:1:1:1, растягивать таблицу на доступную ширину и отдельно форматировать числовые колонки. Ячейки поддерживают вложенные элементы, границы, фон, внутренние отступы, объединение строк и столбцов. Заголовочные строки можно отметить так, чтобы они повторялись на новых страницах; это важнее ручного разбиения, потому что количество строк меняется вместе с данными.
Автоматическая ширина учитывает содержимое, однако длинный непрерывный идентификатор или адрес способен растянуть колонку. Решения: разрешить перенос по дополнительным точкам, уменьшить шрифт конкретной ячейки, ограничить ширину и применять обрезку только там, где потеря текста допустима. Нельзя бездумно уменьшать весь документ до нечитаемого размера. Для финансовых таблиц числа выравниваются по правому краю, единицы измерения не отделяются от значения случайным переносом, а итоговая строка визуально отличается от позиций.
Вложенные таблицы полезны для сложных карточек, но чрезмерная глубина усложняет расчёт макета. Альтернативой служат Div, FlexContainer и пользовательские рендереры. Когда стандартных свойств недостаточно, собственный renderer может измерить доступную область, нарисовать фон, разместить содержимое и вернуть статус FULL, PARTIAL или NOTHING. Такой код требует тестов на коротком и длинном содержимом, иначе ошибка проявится только на границе страницы.
Списки создаются элементом List, для маркеров можно использовать символ, номер, изображение или собственный ILineDrawer. Не следует вставлять маркер обычным символом в начало абзаца: при переносе следующая строка окажется под маркером, а структура тегированного PDF будет неверной. Правильный List сохраняет отступ, нумерацию и семантические элементы L, LI, Lbl и LBody при подготовке доступного документа.
Преобразование HTML и CSS с pdfHTML
pdfHTML преобразует HTML-разметку и CSS в элементы макета, а затем формирует PDF. Это подходит для счетов, писем, сертификатов, отчётов и договоров, которые уже существуют как веб-шаблоны. Преобразователь принимает строку, файл или поток; результат можно сразу записать в PdfDocument либо получить набор элементов для дальнейшего размещения. Второй вариант удобен, когда HTML является только частью документа, например описанием товара между титульной страницей и приложениями.
ConverterProperties объединяет настройки ресурсов и поведения. BaseUri определяет, откуда разрешать относительные пути к изображениям, CSS и шрифтам. Если шаблон содержит img src="/images/logo.png", но базовый каталог не задан, конвертер не найдёт файл при запуске из другой рабочей директории. В серверном процессе лучше вычислять абсолютный контролируемый каталог шаблона и запрещать произвольный доступ к файловой системе через пользовательские значения.
Встроенные стили, таблицы стилей и значительная часть правил CSS применяются во время преобразования, однако модель страницы отличается от окна веб-просмотра. Фиксированная ширина в пикселях, sticky-позиционирование, интерактивные состояния и сценарии не образуют надёжной печатной верстки. Шаблон следует проектировать как печатный: задавать размеры листа, поля, правила разрыва, повтор заголовков и допустимые диапазоны данных. Содержимое, зависящее от выполнения JavaScript, нужно вычислить заранее и передать в готовый HTML.
Большое значение имеет нормализация входа. Незакрытые теги, вложенные интерактивные элементы, противоречивые правила и абсолютные позиции могут давать результат, который формально создаётся, но плохо разбивается по страницам. Перед конвертацией полезно валидировать шаблон, ограничивать размер встроенных изображений, удалять опасные конструкции и проверять, что все обязательные данные подставлены. Пустая строка в адресе или сумме часто не вызывает исключения, поэтому бизнес-проверка должна идти до формирования PDF.
SVG подходит для логотипов, диаграмм и штрихкодов, потому что сохраняет резкость. Внешние ссылки на ресурсы лучше заменять внедрёнными либо разрешать только из доверенного каталога. Сетевой запрос во время генерации создаёт задержки и нестабильность: недоступная картинка меняет внешний вид документа, а пользовательский адрес может превратить конвертер в средство обращения к закрытым узлам. Безопасный resolver должен применять белый список схем, каталогов и размеров.
Преобразование в Document и последующая правка
Метод convertToPdf подходит, когда HTML составляет весь документ. ConvertToDocument возвращает Document и оставляет возможность добавить программные элементы, обработчики страниц, вложения или подпись после конвертации. ConvertToElements полезен для встраивания фрагмента. Важно соблюдать владение ресурсами: если метод создаёт или закрывает Document внутри себя, последующая запись невозможна. Для сложной цепочки лучше явно создать PdfDocument, передать его конвертеру и закрыть в единой точке.
После получения элементов можно изменить отступы, добавить класс доступности, окружить содержимое Div или вставить между частями собственные блоки. Не все CSS-свойства обязаны сохраниться как редактируемые свойства элемента: часть уже учтена рендерером. Поэтому архитектура должна заранее решать, где заканчивается шаблон и начинается программная верстка. Попытка разобрать результат и массово переписать стили сложнее, чем передать нужные правила в CSS.
Тегированная структура и доступность
Тегированный PDF хранит логическую структуру отдельно от визуальных команд. Заголовки, абзацы, списки, таблицы, подписи к полям и альтернативные описания изображений помогают экранным дикторам определить порядок чтения. В iText структура создаётся через роли элементов и свойства доступности. Простое совпадение внешнего вида не гарантирует доступность: текст, нарисованный в произвольных координатах, может оказаться вне дерева тегов или читаться в неожиданной последовательности.
Для документа с таблицей следует обозначить ячейки заголовка как TH, указать область действия строки или столбца и не имитировать таблицу пробелами. Изображению, несущему смысл, задаётся альтернативный текст; декоративный элемент помечается как артефакт, чтобы диктор его пропустил. Язык документа и отдельных фрагментов влияет на произношение. Порядок табуляции форм и ссылок проверяется отдельно от визуального порядка.
Соответствие PDF/UA требует не только тегов, но и корректных метаданных, встроенных шрифтов, однозначного отображения символов, заголовка документа и отсутствия необъяснимого содержимого. Автоматический валидатор обнаруживает структурные нарушения, однако не решает, хорош ли альтернативный текст и логичен ли порядок чтения. Поэтому проверка сочетает машинный отчёт и ручное прохождение клавиатурой или программой экранного доступа.
PDF/A и документы длительного хранения
PDF/A ограничивает функции, которые затрудняют воспроизводимое отображение в будущем. Для создания такого файла указывается конкретный уровень соответствия, цветовой профиль ICC и выходное назначение. Шрифты внедряются, шифрование запрещается, а метаданные должны согласовываться с видимым документом. Если формировать обычный PDF и пытаться исправить его в самом конце, можно столкнуться с множеством зависимых ошибок; проще включить режим соответствия при создании PdfADocument.
При HTML-конвертации профиль передаётся через PdfADocument и ConverterProperties. Изображения с неподходящим цветовым пространством, отсутствующие шрифты и прозрачности обрабатываются согласно выбранному уровню. Выходной ICC-файл должен быть частью контролируемых ресурсов приложения. Нельзя брать произвольный профиль только ради прохождения проверки: он описывает ожидаемое цветовое воспроизведение и влияет на печать.
Уровни с буквой U требуют Unicode-сопоставления текста, а варианты с буквой A дополнительно предъявляют требования к структуре. PDF/A-3 допускает вложения и подходит для электронных счетов, где PDF сопровождается машиночитаемым XML. Вложение должно иметь отношение к основному документу, корректное MIME-описание и метаданные стандарта обмена. Наличие XML само по себе не делает счёт совместимым с отраслевым профилем: нужно проверить схему, бизнес-правила и согласованность сумм.
После генерации документ следует прогнать независимым валидатором. Если отчёт указывает на невнедрённый шрифт, проверяют все пути формирования текста, включая колонтитулы, аннотации и поля формы. Ошибка цветового пространства часто скрывается в PNG с профилем или вставленной странице другого PDF. При объединении соответствующих документов итог не обязательно сохраняет соответствие автоматически: каталоги, метаданные и профили должны быть согласованы заново.
Изменение существующих PDF
Для добавления текста или графики к существующей странице используется PdfCanvas. Новый поток содержимого можно разместить перед старым, чтобы получить фон, или после него, чтобы получить штамп поверх. Порядок важен: водяной знак под непрозрачным изображением не будет виден, а верхний слой способен закрыть подписи и поля. При работе с повернутой страницей координатная система требует преобразования, иначе штамп окажется боком или за пределами видимой области.
Текст на PdfCanvas размещается командами beginText, setFontAndSize, setTextMatrix и showText. Это точный, но низкоуровневый способ: перенос строк, абзацные интервалы и разбиение по страницам придётся рассчитывать самостоятельно. Для блока текста в заданном прямоугольнике удобнее создать Canvas поверх PdfCanvas и добавлять Paragraph. После завершения Canvas закрывают, чтобы рендерер дописал содержимое, но сам PdfDocument остаётся под управлением внешней цепочки.
Изменение текста внутри уже сформированной страницы существенно сложнее добавления. PDF хранит команды рисования, отдельные глифы, позиции и ресурсы, а не абзацы с привычной семантикой. Замена строки той же длины может нарушить кернинг, кодировку, шрифт и расположение. Для шаблонных данных лучше использовать поля AcroForm либо генерировать документ заново. Когда требуется скрыть старый текст, безопасное решение — редактирование содержимого средствами pdfSweep, а не белый прямоугольник и новая надпись.
Аннотации, ссылки, закладки и вложения относятся к объектной структуре, поэтому их можно добавлять без рисования. Ссылка создаётся аннотацией с прямоугольником и действием; визуальный текст может быть отдельным элементом. При копировании страницы между документами ссылки на внутренние страницы и именованные назначения следует проверять: ссылка могла указывать на объект, который не был скопирован или получил другой номер.
Объединение, разбиение и перестановка страниц
PdfMerger копирует выбранные диапазоны страниц из нескольких PdfDocument в целевой документ. Перед объединением полезно проверить пароли, размеры страниц, повороты, формы и подписи. Копирование визуального содержимого не означает сохранения криптографической подписи как действительной: подписанная версия файла изменяется, а подпись может стать недействительной либо относиться только к исходному диапазону байтов. Если юридическая значимость важна, объединяют до подписания или помещают исходные файлы как вложения.
Для разбиения применяют PdfSplitter или собственный цикл копирования страниц. Критерий может быть числовым, по закладкам, штрихкоду, текстовому маркеру или размеру результата. При разделении большого пакета писем нельзя ограничиться номерами страниц, если количество листов меняется. Надёжнее находить начало документа по распознанному идентификатору и проверять, что каждый фрагмент содержит обязательные поля.
Перестановка выполняется копированием страниц в новом порядке или методом перемещения в пределах документа. Следует учитывать структуру тегов, дерево страниц, закладки, ссылки и номера страниц, напечатанные в содержимом. Визуальный номер, нарисованный в колонтитуле, не изменится автоматически. Для документов с оглавлением после перестановки требуется заново сформировать оглавление или обновить назначения.
SmartMode помогает повторно использовать одинаковые ресурсы при копировании: изображения и шрифты сравниваются и не записываются заново, когда это возможно. Режим экономит место, но хранит дополнительную информацию для сопоставления и увеличивает потребление памяти. На сотнях больших файлов следует измерить оба варианта и ограничить размер пакета. Иногда последовательная обработка небольшими группами даёт более предсказуемую нагрузку, чем один гигантский PdfDocument.
Водяные знаки, штампы и служебные метки
Водяной знак может быть текстом, изображением или прозрачной графикой. Прозрачность задаётся через ExtGState, после чего состояние графики сохраняют и восстанавливают, чтобы оно не повлияло на последующие элементы. Для диагонального текста вычисляют центр страницы и матрицу поворота. Если страницы имеют разные размеры, координаты пересчитываются для каждой, а не берутся из первого листа.
Для повторяемого штампа эффективен PdfFormXObject: логотип, рамка и постоянные надписи рисуются один раз, затем объект размещается на каждой странице. Переменная часть, например имя получателя или статус, выводится отдельно. Такой подход уменьшает размер и ускоряет обработку. Однако при использовании прозрачности и цветовых профилей в PDF/A нужно убедиться, что XObject соответствует выбранному уровню.
Штрихкоды и QR-коды формируются как векторный объект либо изображение. Данные должны проходить бизнес-проверку до кодирования: неверная контрольная сумма будет напечатана без предупреждения, если её не проверяет конкретный класс. Для сканирования оставляют тихую зону, не растягивают код непропорционально и проверяют распечатку при реальном размере. Цветной фон и низкий контраст ухудшают считывание даже при идеальной геометрии PDF.
Служебная отметка черновик не является защитой. Пользователь может извлечь содержимое, а другой процесс — удалить или перекрыть штамп. Если документ нельзя использовать как окончательный, это должно отражаться в данных, подписи, правах доступа и процессе публикации. Водяной знак лишь помогает визуально различать состояние.
Поля AcroForm: создание, заполнение и выравнивание
AcroForm хранит интерактивные поля отдельно от обычного содержимого страницы. PdfAcroForm предоставляет доступ к словарю полей, а фабрики создают текстовые поля, флажки, переключатели, списки, раскрывающиеся элементы и кнопки. У поля есть полное имя, значение, прямоугольник виджета, внешний вид и свойства. Имена должны быть уникальными и устойчивыми, потому что именно по ним приложение подставляет данные.
При заполнении сначала получают поле по имени, проверяют его существование и тип, затем устанавливают значение. Молчаливое пропускание отсутствующего поля опасно: шаблон могли изменить, и документ выйдет без суммы или фамилии. Производственный код сравнивает набор ожидаемых полей с фактическим, записывает расхождения и прекращает выпуск критичного документа. Для необязательных полей допустима явная политика пропуска.
Внешний вид поля может не обновиться автоматически во всех просмотрщиках. Надёжный результат требует шрифта с нужными символами и генерации appearance stream. Флаг NeedAppearances перекладывает эту задачу на просмотрщик и даёт разный результат в разных программах. Для итогового файла лучше сформировать внешний вид средствами библиотеки, проверить кириллицу, размер текста, выравнивание и многострочный режим.
Flatten превращает поля и их внешний вид в обычное содержимое страницы, после чего редактирование формы становится недоступным. Это удобно для финальной копии, но выполняется только после заполнения и проверки. Если внешний вид пуст, flatten закрепит пустое место. Подписываемое поле нельзя бездумно выравнивать после подписи: изменение документа влияет на допустимые изменения и результат проверки.
HTML-формы можно преобразовать в AcroForm-поля через pdfHTML, если включены соответствующие настройки. Имена, типы и размеры берутся из разметки, но шаблон следует адаптировать для печати. Поле, удобное на экране, может оказаться слишком низким для встроенного шрифта. После конвертации полезно пройти по полям, применить единый шрифт, формат чисел и правила обязательности.
Работа с XFA
XFA использует XML-шаблоны и модель данных, отличающиеся от AcroForm. pdfXFA предназначен для заполнения, преобразования и уплощения таких документов. Перед обработкой важно определить, содержит ли файл XFA и является ли форма динамической. Простая попытка работать с ней как с обычными полями может вернуть неполный набор либо не изменить визуальный слой.
Уплощение XFA формирует статические страницы из шаблона и данных. Результат легче открывается в широком наборе просмотрщиков и подходит для дальнейшего хранения, но интерактивность и правила формы теряются. До уплощения проверяют раскрывающиеся секции, повторяющиеся строки, вычисляемые значения и шрифты. Если шаблон ссылается на внешние ресурсы, они должны быть доступны в контролируемом окружении.
Цифровые подписи и проверяемая цепочка
Цифровая подпись связывает хеш определённого состояния PDF с закрытым ключом и сертификатом. PdfSigner предоставляет базовый процесс, а PdfPadesSigner упрощает профили PAdES, метку времени и долгосрочную проверку. Подпись записывается инкрементально: исходные байты сохраняются, к ним добавляются новые объекты и словарь подписи. Перезапись всего файла после подписания разрушит эту связь.
Ключ может находиться в PKCS#12, HSM, облачном сервисе подписи или системном хранилище. Библиотека не должна получать экспортируемый ключ, если политика требует аппаратной защиты: применяется внешняя реализация подписи, которая принимает хеш и возвращает криптографический результат. Для удалённой подписи процесс разделяют на подготовку диапазона байтов, отправку дайджеста и внедрение полученного контейнера с заранее зарезервированным размером.
Видимая подпись — это appearance, а не доказательство сама по себе. В прямоугольнике можно показать имя, дату, причину, логотип и графическое воспроизведение, но проверять нужно криптографический словарь, цепочку сертификатов и статус отзыва. Обратная ситуация тоже возможна: подпись действительна, хотя на странице нет видимого штампа. Интерфейс приложения должен явно различать эти понятия.
Шаблон HTML может содержать специальный элемент, который преобразуется в поле подписи с заданным именем и размером. Затем код находит поле и подписывает его. Такой подход удобен для договоров: дизайнер управляет расположением в HTML, а криптографическая часть не зависит от координат. Имя поля нужно согласовать между шаблоном и приложением; иначе подпись будет создана в новом невидимом поле или операция завершится ошибкой.
Метка времени подтверждает существование подписи в определённый момент, а OCSP и CRL сообщают о статусе сертификата. Для долгосрочной проверки данные валидации встраиваются в DSS, затем может добавляться документная метка времени. Сетевые ответы следует кэшировать по правилам безопасности и проверять их подписи. Недоступность сервера статуса нельзя трактовать как автоматическую действительность либо недействительность сертификата: приложение должно возвращать отдельное состояние неопределённости.
Последовательность нескольких подписей проектируют заранее. Сертифицирующая подпись может разрешить заполнение форм и последующие подписи, но запретить другие изменения. Если после первой подписи добавить страницу или изменить обычное содержимое, проверщик покажет нарушение разрешений. Перед каждым шагом следует анализировать существующие подписи, уровень DocMDP и список допустимых изменений.
Пароли, шифрование и разрешения
StandardProtection создаёт пользовательский пароль для открытия и пароль владельца для изменения настроек. Можно разрешить или запретить печать, копирование, изменение и заполнение форм. Эти флаги помогают корректным просмотрщикам соблюдать политику, но не являются абсолютной защитой после того, как пользователь получил расшифрованное содержимое. Для действительно секретных документов важны управление доступом, срок действия ссылки, журнал выдачи и шифрование хранилища.
Алгоритм и длина ключа выбираются настройками WriterProperties. Для совместимости со старыми устройствами иногда пытаются использовать устаревшие варианты, однако это ослабляет защиту. Следует определить минимально поддерживаемые просмотрщики и применять современный алгоритм. Пароли не должны храниться в коде, командной строке или журнале; их получают из защищённого секрета и передают в виде массива байтов с минимальным временем жизни.
Открытие защищённого PDF выполняется ReaderProperties с паролем. Ошибку неверного пароля нужно отличать от повреждения файла и неподдерживаемого алгоритма. Пакетная задача не должна многократно перебирать пароли: это создаёт риск блокировки внешнего хранилища и скрывает проблему маршрутизации. Надёжнее связать пароль с конкретным клиентом или заданием и фиксировать отказ без вывода секрета.
Шифрование несовместимо с некоторыми профилями долговременного хранения. Если нужен и защищённый транспорт, и PDF/A, документ создают соответствующим стандарту, а защиту обеспечивают контейнером, каналом доставки или правами доступа. Попытка добавить пароль к PDF/A приведёт к нарушению соответствия.
Безопасное удаление данных с pdfSweep
Закрашивание текста чёрным прямоугольником скрывает его только визуально. Символы могут остаться в потоке содержимого, копироваться в буфер, находиться поиском или извлекаться анализатором. pdfSweep выполняет настоящее редактирование: определяет области или совпадения текста и удаляет затронутые команды, изображения и графику, после чего при необходимости рисует заменяющую заливку.
Области задаются прямоугольниками по страницам либо стратегиями поиска. Регулярные выражения подходят для номеров карт, паспортов, адресов электронной почты и внутренних идентификаторов, но требуют осторожности. Шаблон должен учитывать разделители, перенос строки и разные варианты записи. Перед применением полезно получить список найденных фрагментов с координатами, показать его оператору или сравнить с ожидаемым количеством.
Параметр доли перекрытия определяет, насколько символ или графический объект должен попадать в область, чтобы быть удалённым. Нулевое значение захватывает даже минимальное пересечение и может удалить соседние буквы; значение, близкое к единице, способно оставить часть объекта. Подходящее значение проверяют на реальных шрифтах, наклонном тексте и таблицах. Для критичных задач область расширяют на небольшой безопасный отступ и проводят извлечение текста после обработки.
Изображение может содержать персональные данные внутри одного растрового объекта. Если область пересекает изображение, инструмент должен изменить растровые данные, а не просто положить сверху фигуру. После обработки проверяют визуальный результат и внутреннее содержимое: извлекают текст, изображения и объекты, ищут исходные последовательности в байтах и тестируют копирование. Один тест просмотром недостаточен.
Редактирование следует выполнять до подписи. Любое последующее удаление меняет документ и нарушает подпись. Если требуется доказать процесс, сначала создают очищенный файл, фиксируют журнал правил и контрольную сумму, затем подписывают результат. Журнал не должен содержать удалённые секреты целиком; достаточно типа правила, количества совпадений, страниц и технического идентификатора задания.
Извлечение текста, координат и изображений
PdfTextExtractor использует стратегию, которая получает события отображения текста и строит строку. Простая стратегия сохраняет порядок операторов, а стратегия с учётом расположения пытается восстановить визуальные строки и пробелы. Ни одна не превращает произвольный PDF в идеальный документ: в файле могут быть отдельные буквы, колонки, таблицы, повернутые фрагменты и нестандартное сопоставление шрифта.
Для поиска с координатами реализуют IEventListener или фильтр событий. Каждый TextRenderInfo содержит базовую линию, ограничивающие прямоугольники, шрифт и Unicode-представление. Из нескольких фрагментов собирают слова с допуском по расстоянию и направлению. Такой подход нужен, чтобы найти подпись Итого и взять число справа, но правила должны учитывать масштаб, поворот и разные шаблоны.
Извлечение таблицы является задачей интерпретации. Если в PDF нет структурных тегов, границы и текст приходится группировать геометрически: определить строки по вертикальному положению, столбцы по диапазонам X, учесть объединённые ячейки и переносы. Тонкие линии могут быть векторными объектами или отсутствовать. Для стабильного процесса лучше получать исходные данные до PDF либо формировать тегированную таблицу, а извлечение использовать как резервный путь.
Изображения находятся в ресурсах страниц и XObject. Один объект может использоваться много раз с разными матрицами, а маска прозрачности — храниться отдельно. При сохранении изображения следует учитывать исходный фильтр: JPEG можно извлечь без повторного сжатия, тогда как некоторые цветовые пространства требуют преобразования. Позицию на странице получают из текущей матрицы преобразования в обработчике событий.
Если извлечённый текст пуст, сначала проверяют, является ли страница сканом. Затем смотрят наличие ToUnicode у шрифта и возможность копирования в обычном просмотрщике. Пустой или бессмысленный результат не всегда означает ошибку библиотеки: PDF мог хранить только глифовые коды без таблицы соответствия. В таком случае помогает OCR либо специализированное сопоставление шрифта, если известна кодировка.
Распознавание сканов с pdfOCR
pdfOCR превращает изображения страниц в текстовый слой и может сформировать поисковый PDF, включая профиль PDF/A-3u. Движок распознавания выбирается отдельно; доступны интеграции с Tesseract и ONNX-моделями, а архитектура допускает собственную реализацию. Процесс состоит из рендеринга или чтения изображений, подготовки, распознавания, сопоставления координат и записи невидимого текста поверх исходного изображения.
Качество сильнее всего зависит от входа. Разрешение около 300 точек на дюйм обычно подходит для печатного текста, но мелкий шрифт требует большего. Перекос, поворот на 90 градусов, шум, просвечивание обратной стороны и низкий контраст ухудшают результат. До OCR полезны определение ориентации, выравнивание, обрезка полей, удаление фона и адаптивная бинаризация; параметры проверяют на репрезентативной выборке, а не на одном чистом листе.
Языковой набор должен соответствовать документу. Подключение десятков языков одновременно увеличивает время и число ложных вариантов. Для пакета на русском и английском выбирают эти модели, а для документов с отдельными участками другого языка можно применять разные настройки по страницам. Особое внимание требуется похожим символам: латинская C и кириллическая С, цифра 0 и буква О могут пройти визуальную проверку, но сломать поиск и идентификаторы.
Поисковый слой должен точно совпадать с изображением. Ошибка масштаба или rotation приводит к выделению текста в другом месте. После генерации проверяют поиск нескольких слов, копирование абзаца и координаты выделения. Для PDF/A дополнительно проверяют шрифты, Unicode и метаданные. Невидимый текст не следует делать полностью прозрачной графикой, если это нарушает профиль; используется предусмотренный текстовый режим отображения.
Распознавание не гарантирует юридическую точность. Для номеров договоров, сумм и персональных данных применяются контрольные правила: регулярные выражения, словари, сверка контрольных сумм и ручная очередь для низкой уверенности. В результате хранят исходную страницу, распознанный текст, показатели качества и версию модели, чтобы воспроизвести решение.
Пакетную обработку ограничивают по числу параллельных страниц и памяти модели. Один процесс может использовать CPU либо поддерживаемый GPU, но одновременный запуск слишком большого числа задач приводит к обмену памятью и падению производительности. Лучше измерить время на типовых документах, задать очередь и сохранять промежуточный статус по страницам, чтобы сбой не заставлял распознавать всё заново.
Оптимизация размера с pdfOptimizer
Размер PDF складывается из изображений, шрифтов, потоков содержимого, вложений и служебных объектов. pdfOptimizer применяет стратегии к отдельным категориям, а не просто сжимает файл. Для изображений можно снижать разрешение и качество, преобразовывать формат и удалять лишние данные. Для шрифтов — формировать подмножества и устранять неиспользуемые ресурсы. Правильная конфигурация зависит от назначения: экранный отчёт и чертёж для печати требуют разных порогов.
Перед уменьшением изображений рассчитывают эффективное разрешение на странице. Фотография в 4000 пикселей, размещённая шириной 5 сантиметров, избыточна для экрана; та же фотография на полном листе может быть приемлемой. Нельзя оценивать только размер исходного файла. Схемы, мелкий текст и штрихкоды плохо переносят JPEG-сжатие, поэтому для них сохраняют без потерь или исключают из агрессивной стратегии.
Оптимизация после подписания недопустима, поскольку меняет байты. Её выполняют до добавления окончательных подписей и меток времени. Также проверяют PDF/A, PDF/UA и цветовые профили: удаление ресурса, который кажется неиспользуемым, или изменение цветового пространства может нарушить соответствие. После каждого профиля оптимизации запускают валидатор и визуальное сравнение.
Самый маленький файл не всегда лучший. Слишком сильное подмножество шрифта затрудняет последующее заполнение формы, низкое разрешение делает печать нечитаемой, а удаление метаданных может убрать нужный идентификатор. Политику задают измеримыми целями: верхний размер, минимальное разрешение, допустимое изменение качества и перечень сохраняемых объектов. Решение принимается по нескольким типам документов, включая худший случай.
Метаданные, вложения и портфели данных
Свойства документа включают заголовок, автора, тему, ключевые слова и даты. Более структурированные сведения хранятся в XMP. Для стандартов и отраслевых профилей XMP содержит схемы, версии и идентификаторы. Значения в Info и XMP не должны противоречить друг другу. При копировании страниц метаданные исходников не сливаются автоматически в осмысленный итог; их формирует приложение согласно назначению нового документа.
Файл можно прикрепить к PDF как embedded file и связать с документом отношением AFRelationship. Это применяется для XML электронного счёта, исходных данных, спецификации или подписанного приложения. Имя, описание, MIME-тип и параметры должны быть корректны. Перед вложением следует ограничить размер и тип, проверить содержимое и исключить исполняемые файлы, если они не нужны бизнес-процессу.
Вложения увеличивают размер и могут быть незаметны пользователю, который смотрит только страницы. Интерфейс выдачи должен сообщать о них, а тест — перечислять имена и контрольные суммы. При оптимизации и объединении проверяют, что вложения не потеряны и не дублированы. Если данные предназначены для автоматического импорта, договоритесь о точном имени, кодировке и схеме, а не ищите первый XML в контейнере.
Производительность и обработка больших объёмов
Главная ошибка пакетного процесса — держать все входные и выходные документы в памяти одновременно. Потоковая обработка открывает один файл, выполняет действия, закрывает и публикует результат, после чего освобождает ссылки. Для объединения всё равно требуется открывать несколько входов, но их можно копировать последовательно. Изображения декодируются в значительный объём памяти, поэтому лимит по размеру файла не заменяет лимита по пикселям.
Объекты PdfDocument не предназначены для одновременного изменения из нескольких потоков. Параллелизм строят на уровне независимых документов: каждое задание имеет собственные reader, writer, шрифтовые ресурсы и временный каталог. Общие неизменяемые данные можно кэшировать осторожно, но объект шрифта, связанный с конкретным PdfDocument, нельзя переносить в другой документ. При сомнении создают PdfFont на документ из общего массива байтов программы шрифта.
Скорость измеряют по этапам: загрузка, разбор, верстка, OCR, оптимизация, подпись, проверка и запись. Общая цифра не показывает узкое место. Для HTML часто доминируют изображения и шрифты, для OCR — модель, для подписи — сетевые запросы к службам статуса. Метрики должны включать число страниц, входной и выходной размер, пик времени и тип операции.
Временные файлы необходимы, когда результат нельзя считать успешным до закрытия и проверки. Имя генерируют в том же файловом разделе, чтобы финальная смена имени была атомарной. После сбоя временные объекты удаляются по политике очистки, но не раньше записи диагностики. В облачном хранилище аналогом является загрузка под временным ключом и смена статуса или копирование после проверки.
Ограничения защищают сервис от случайных и враждебных входов: максимальное число страниц, глубина объектов, размер распакованного потока, количество изображений, время операции и размер результата. PDF может быть небольшим на диске, но содержать сильно сжатые ресурсы. Обработку следует запускать с лимитами процесса и отменой, а не полагаться только на проверку длины массива.
Интеграция в веб‑системы и фоновые задания
В обработчике запроса можно сформировать PDF в MemoryStream и вернуть байты с корректным MIME-типом и именем. Такой вариант удобен для короткого отчёта, но длительные конвертации и OCR лучше выполнять через очередь. Пользователь получает идентификатор задания, а рабочий процесс сохраняет вход, формирует результат, проверяет его и публикует состояние. Повторный запрос с тем же идемпотентным ключом не должен выпускать несколько разных документов.
Шаблоны и ресурсы версионируют вместе с кодом. Если дизайнер изменил CSS или шрифт, тот же набор данных может дать другое разбиение страниц и контрольную сумму. В документе или журнале полезно хранить идентификатор шаблона, но не техническую информацию, которая не нужна получателю. При расследовании можно воспроизвести результат по данным, шаблону и конфигурации.
Ошибки делятся на пользовательские и системные. Неверный пароль, неподдерживаемый вход или отсутствующее обязательное поле можно вернуть как понятную причину. Нехватка памяти, сбой подписи и повреждение временного хранилища требуют повторной попытки или вмешательства. Не следует возвращать наружу стек вызовов, пути файлов и содержимое документа; они остаются в защищённом журнале с маскированием данных.
Когда PDF формируется из недоверенного HTML, шаблон и данные разделяют. Пользователю разрешают текст и ограниченный набор полей, но не произвольные стили, пути и вложения. Если произвольная разметка действительно необходима, ввод очищают, сетевой доступ ресурсов закрывают белым списком, а процесс запускают в изолированной среде с лимитами. Это снижает риск чтения файлов, обращения к внутренним адресам и исчерпания памяти огромным изображением.
Проверка результата и автоматические тесты
Тест файл открылся недостаточен. Структурная проверка открывает PDF новым PdfReader, сверяет число страниц, размер, наличие обязательных метаданных, полей, вложений и закладок. Для форм проверяются значения и appearance, для подписи — целостность и цепочка, для PDF/A и PDF/UA — отчёт валидатора. Ошибка одного обязательного условия блокирует публикацию.
Визуальный регрессионный тест рендерит страницы в изображения и сравнивает с эталоном с допустимым порогом. Он находит сдвиг таблицы, замену шрифта, пропавшую картинку и неверный цвет. Сравнение байтов PDF бесполезно как единственный метод: даты, идентификаторы, порядок объектов и сжатие могут менять файл без визуального отличия. Эталон обновляют только после осознанной проверки.
Текстовый тест извлекает содержимое и проверяет ключевые значения, но учитывает порядок и переносы. Для суммы лучше искать нормализованное значение и подпись поля, а не сравнивать весь текст одной строкой. Для документа на нескольких языках проверяют несколько характерных слов и отсутствие символа замены. В OCR-сценарии дополнительно измеряют долю распознанных обязательных полей.
Граничные наборы включают пустой список, одну строку, максимальное число строк, очень длинное имя, отрицательную сумму, разные десятичные разделители, кириллицу, арабское письмо, эмодзи, высокое изображение и повреждённый вход. Именно такие данные выявляют переполнение, отсутствующие глифы и неверные разрывы. Тестовый набор должен отражать реальные шаблоны, а не только искусственный Hello, PDF.
После обновления зависимостей прогоняют весь набор. Компоненты Suite должны соответствовать одной строке таблицы совместимости: Core и дополнения используют согласованные API. Случайное смешение версий может компилироваться, но завершиться NoSuchMethodError, MissingMethodException или иной ошибкой во время выполнения. Файл блокировки зависимостей и централизованное управление версиями уменьшают риск.
Типичные ошибки и способы исправления
Файл пустой или не открывается
Сначала проверяют, закрыты ли Document и PdfDocument до чтения выходного массива. Затем убеждаются, что поток не был закрыт раньше времени и позиция MemoryStream установлена правильно перед чтением. Если исключение произошло в середине, результат не публикуют. Повторное открытие новым PdfReader сразу после генерации даёт быструю проверку целостности.
PDF header not found и повреждённая таблица ссылок
Сообщение о заголовке обычно означает, что вход не является PDF, обрезан, содержит HTML-страницу ошибки или передан не с начала потока. Нужно проверить первые байты, длину и MIME-тип на этапе загрузки. Некоторые повреждённые документы могут быть восстановлены читателем, но предупреждения нельзя игнорировать: сохраните отдельный результат и сравните страницы, формы, вложения и подписи.
Кириллица отображается квадратами
Причина — шрифт без нужных глифов, неверная кодировка или отсутствие внедрения. Подключите подходящий TTF или OTF, создайте PdfFont с Unicode-кодировкой и используйте его во всех элементах, включая поля и колонтитулы. В pdfHTML зарегистрируйте семейство в FontProvider и проверьте, что CSS ссылается на то же имя. Не рассчитывайте на шрифт, установленный только на рабочем компьютере.
Изображения и CSS пропадают при HTML-конвертации
Проверьте BaseUri, регистр имён файлов, разрешение относительных путей и правила доступа resolver. В контейнере Linux путь чувствителен к регистру, хотя шаблон мог работать на другой системе. Для ресурса из памяти создайте собственный поставщик. Убедитесь, что формат изображения поддерживается и содержимое действительно соответствует расширению.
Таблица выходит за правый край
Проверьте сумму фиксированных ширин, поля страницы и внутренние отступы ячеек. Длинные непрерывные строки должны иметь стратегию переноса. Для широкого отчёта используйте альбомную страницу либо разбейте данные на несколько таблиц, а не уменьшайте шрифт до неразборчивого. В тестах добавьте максимальные реальные значения каждого столбца.
Предупреждение о невозможности разместить элемент
Чаще всего элемент помечен KeepTogether, но физически выше доступной страницы, либо пользовательский renderer возвращает NOTHING без изменения условия. Снимите неделимость для длинного блока, разрешите разрыв таблицы и проверьте поля. Для изображения задайте масштабирование до доступной области. Повторяющееся предупреждение нельзя просто скрыть: оно может означать потерю содержимого.
Подпись становится недействительной
После подписания документ был переписан или изменён недопустимым способом. Используйте append mode и подписывайте финальную версию после оптимизации, редактирования и заполнения. Для нескольких подписей соблюдайте разрешения сертифицирующей подписи. Проверяйте существующие подписи до изменения и не объединяйте подписанный PDF как обычные страницы, если требуется сохранить юридическое состояние.
Не найден криптографический провайдер
Функции подписи зависят от согласованного криптографического адаптера и его библиотек. Добавьте рекомендуемый адаптер для выбранной среды, исключите конфликтующие старые пакеты и проверьте дерево зависимостей. В Java убедитесь, что провайдер доступен модульной системе; в .NET — что нативные и управляемые компоненты соответствуют целевой платформе. После исправления выполните реальную подпись и проверку, а не только запуск приложения.
Метод или класс отсутствует во время выполнения
NoSuchMethodError и MissingMethodException обычно указывают на несовместимые версии Core и дополнения либо на дубли пакетов в итоговой сборке. Сверьте таблицу совместимости, очистите кэш сборки, изучите Maven dependency:tree или список NuGet transitive dependencies. Исключите старую копию из контейнера приложения и закрепите единый набор версий.
Потребление памяти растёт на каждом документе
Проверьте закрытие PdfDocument, потоков и временных изображений, а также коллекции, где сохраняются результаты. Не держите байты всех файлов для общего отчёта. Ограничьте параллелизм и снимите профиль памяти на серии одинаковых заданий. SmartMode и OCR-модели используют кэш; он должен быть осознанным и ограниченным, а не случайно привязанным к глобальному списку.
AGPL конфликтует с моделью распространения
Открытая лицензия требует соблюдения её условий, включая предоставление соответствующего исходного кода пользователям взаимодействующего решения. Если проект не может выполнять эти требования, до интеграции нужна коммерческая лицензия и проверка условий юристом. Нельзя считать, что библиотека бесплатна без ограничений только потому, что пакет доступен из публичного репозитория.
Практический сценарий: счёт из данных
Конвейер начинается с модели заказа, прошедшей проверку: номера, даты, реквизиты, позиции, налоги и итоговые суммы. Денежные значения хранятся десятичным типом, округление выполняется по бизнес-правилам до верстки. Шаблон задаёт шапку, адреса, таблицу и подписи, но не пересчитывает критичные суммы. Код передаёт уже согласованные значения и проверяет, что итог в PDF совпадает с моделью.
Для многостраничного счёта таблица повторяет заголовок, позиции могут переноситься, а строка итога держится вместе с несколькими предыдущими строками, если это возможно. Номер страницы и идентификатор заказа выводятся в колонтитуле. Логотип и шрифты берутся из версионированного набора ресурсов. После создания тест извлекает номер и сумму, проверяет число страниц, наличие встроенных шрифтов и допустимый размер.
Если нужен электронный счёт с XML, файл данных прикрепляется с правильным отношением и метаданными. PDF формируется в требуемом профиле PDF/A, затем независимый валидатор проверяет контейнер и XML. Подпись добавляется после оптимизации и всех вложений. Результат публикуется только после успешной структурной и криптографической проверки.
Практический сценарий: отчёт из HTML
Шаблон делится на компоненты: титульная часть, сводные показатели, таблицы, графики и примечания. Сервер заранее строит статический HTML, внедряет безопасные данные с экранированием и сохраняет изображения графиков либо SVG. ConverterProperties получает базовый каталог и FontProvider. Правила печати задают размеры страницы, разрывы и повтор строк таблицы.
Проблемные наборы данных проверяются до запуска: пустой отчёт, сотни строк, длинные названия, отрицательные значения и отсутствующее изображение. После конвертации добавляются метаданные, закладки и обработчик колонтитула. Если требуется PDF/UA, шаблон использует семантические заголовки, списки и таблицы, а изображения получают альтернативные описания.
Визуальный тест рендерит первые, средние и последние страницы. Структурный тест ищет ключевые значения и проверяет дерево тегов. Такой процесс позволяет дизайнеру менять CSS, но не выпускает изменение, пока контрольные примеры не прошли сравнение.
Практический сценарий: пакетное скрытие персональных данных
Сначала формируется набор правил: точные идентификаторы из базы, регулярные выражения и прямоугольники для стабильных шаблонов. Этап обнаружения сохраняет только маскированные сведения и координаты, затем сравнивает число совпадений с ожидаемым. Документы с нулём или аномально большим количеством отправляются на ручную проверку.
На этапе применения pdfSweep удаляет содержимое, при необходимости добавляет нейтральную заливку и служебную причину без раскрытия исходных данных. После закрытия результат повторно анализируется: поиск не должен находить секрет, извлечение изображений не должно возвращать исходный фрагмент, а визуальный снимок подтверждает целостность остальной страницы.
Очищенный документ получает новый идентификатор и контрольную сумму. Исходный объект остаётся в защищённом контуре согласно политике хранения, а наружу публикуется только проверенный результат. Подписание выполняется в самом конце, иначе операция удаления нарушит подпись.
Практический сценарий: заполнение и подписание договора
Шаблон формы содержит устойчивые имена полей и заранее подготовленное поле подписи. Приложение сверяет схему, заполняет текст, даты, суммы и флажки, создаёт внешний вид с внедрённым шрифтом и блокирует выпуск при отсутствии обязательного поля. До подписи оператор или автоматический тест проверяет видимую страницу и значения в словаре AcroForm.
Затем документ оптимизируется, если это нужно, и передаётся процессу подписи. Закрытый ключ остаётся в защищённом хранилище, а приложение отправляет только подготовленный хеш. После внедрения подписи выполняется проверка целостности, цепочки и метки времени. Финальный файл больше не проходит через операции, которые переписывают содержимое.
Если договор подписывают несколько сторон, каждое поле имеет своё имя и порядок. Первая подпись разрешает последующее заполнение только в предусмотренных пределах. Перед второй подписью система проверяет, что первая действительна и изменения допустимы. Такой контроль предотвращает ситуацию, когда внешне все штампы присутствуют, но одна подпись уже нарушена.
Сравнение iText Suite с аналогами
| Программа | Лучше подходит для | Главное ограничение |
|---|---|---|
| iText Suite | Комплексных Java- и .NET-конвейеров: создание, изменение, HTML, формы, подписи, OCR, редактирование данных и стандарты PDF | Для закрытого продукта обычно требуется коммерческая лицензия |
| Apache PDFBox | Открытой Java-обработки страниц, текста, форм, разделения, объединения, рендеринга и базовой подписи | Сложную верстку и отраслевые процессы приходится собирать из низкоуровневых API |
| OpenPDF | Java-проектов, которым нужна лицензия LGPL/MPL и знакомая объектная модель для создания и изменения PDF | Набор специализированных компонентов и проверенных корпоративных сценариев уже |
| QuestPDF | Декларативной генерации новых документов в C# с удобной компоновкой таблиц, текста и повторяющихся блоков | Основной акцент сделан на генерации, а не на глубоком изменении произвольных PDF |
| PDFsharp и MigraDoc | .NET-задач создания, рисования, объединения и разбиения, где достаточно базовой модели макета | PDFsharp даёт только базовую текстовую верстку, сложные разрывы требует MigraDoc |
| Apryse SDK | Приложений, которым кроме серверной обработки нужны просмотр, аннотации и широкий готовый функционал PDF | Проприетарная платформа требует отдельного лицензирования и более крупной интеграции |
iText Suite стоит выбирать, когда один процесс должен одновременно генерировать документы, работать с существующими страницами, обеспечивать PDF/A или PDF/UA, заполнять формы, подписывать, распознавать и безопасно удалять данные. Apache PDFBox подходит для Java-проектов с открытой лицензией и готовностью писать больше инфраструктурного кода. OpenPDF полезен при совместимой объектной модели и требованиях LGPL/MPL. QuestPDF особенно удобен для новой декларативной верстки в C#, а PDFsharp с MigraDoc — для более простых .NET-документов. Apryse SDK рационален, когда обработка должна сочетаться с полноценным просмотром и интерактивными инструментами.
Как выбрать компоненты для конкретной задачи
Начинайте с операции, а не со списка пакетов. Для создания и изменения PDF, страниц, метаданных, форм и базовой верстки нужен Core. Для преобразования HTML добавляется pdfHTML, для сложной типографики — pdfCalligraph, для безопасного удаления — pdfSweep, для OCR — pdfOCR, для XFA — pdfXFA, для целевого уменьшения размера — pdfOptimizer. Подключение всего набора без необходимости увеличивает размер зависимостей, поверхность обновления и время диагностики.
Следующий критерий — стандарт результата. Если нужен обычный внутренний отчёт, достаточно проверить шрифты и просмотр. Для долговременного хранения проектируется PDF/A, для доступности — PDF/UA и семантика, для квалифицированного обмена — профиль подписи и данные валидации, для электронного счёта — PDF/A-3 и XML по отраслевой схеме. Стандарт влияет на архитектуру с первого шага, а не является галочкой после генерации.
Третий критерий — доверие к входу. Создание из собственных данных существенно предсказуемее обработки неизвестных файлов. Для внешнего PDF устанавливаются лимиты, изоляция и проверка повреждений. Для внешнего HTML закрывается произвольный доступ к ресурсам. Для OCR ограничивается число пикселей и время. Для подписи секреты выносятся из процесса формирования документа.
Четвёртый критерий — лицензирование. До включения зависимости в продукт определите, можете ли вы выполнять AGPL, или нужна коммерческая лицензия. Решение фиксируется вместе с перечнем компонентов и способом распространения. Это предотвращает позднюю замену библиотеки, когда шаблоны, тесты и процессы уже завязаны на конкретный API.
Контрольный список перед вводом в эксплуатацию
- Все компоненты выбраны из совместимого набора и закреплены в файле зависимостей.
- Шрифты покрывают все языки, имеют разрешение на внедрение и поставляются вместе с приложением.
- HTML-ресурсы разрешаются только из доверенных каталогов, а пользовательские данные экранируются.
- Ограничены размер, число страниц, пиксели изображений, время операции и параллелизм.
- Результат повторно открывается, а обязательные страницы, поля, вложения и метаданные проверяются.
- PDF/A, PDF/UA и подписи проходят независимую профильную проверку.
- Оптимизация, редактирование данных и заполнение выполняются до окончательной подписи.
- Временная запись и атомарная публикация защищают исходный файл от повреждения.
- Журнал содержит идентификаторы и причины ошибок, но не пароли, ключи и полный конфиденциальный текст.
- Регрессионный набор включает длинные строки, разные письменности, крупные изображения и повреждённые входы.
Устойчивый порядок операций
Для нового документа рациональная последовательность выглядит так: проверить данные, подготовить шрифты и ресурсы, создать PdfDocument требуемого профиля, сформировать страницы, добавить метаданные и вложения, закрыть документ, повторно открыть и проверить, при необходимости оптимизировать, затем подписать и выполнить окончательную проверку. Если после подписи обнаружена ошибка, создаётся новая версия документа и новая подпись; исправлять подписанные байты нельзя.
Для существующего PDF порядок иной: проверить тип и пароль, открыть отдельный выход, проанализировать страницы и подписи, выполнить разрешённые изменения, заполнить или уплощить формы, удалить конфиденциальные фрагменты, проверить извлечением и рендерингом, оптимизировать и только затем подписать. Операции, которые могут повредить соответствие стандарту, сопровождаются повторной валидацией.
Для скана сначала оценивают качество и ориентацию, затем запускают OCR с ограниченным набором языков, проверяют обязательные поля и геометрию текстового слоя, формируют требуемый профиль PDF, оптимизируют изображения без потери читаемости и подписывают. Хранение показателей OCR помогает отделять технически созданный файл от документа, пригодного для автоматического поиска.
Главное преимущество iText Suite проявляется там, где обработка должна быть детерминированной и проверяемой. Один раз описанные правила применяются одинаково к каждому файлу, а тесты фиксируют структуру, вид, текст, соответствие стандарту и подпись. Такой конвейер требует инженерной подготовки, зато исключает ручные расхождения и позволяет точно определить, на каком этапе возникла проблема и какие данные нужно исправить.