Перейти к содержимому

Контракты / Извлечение

Область извлечения определяет контракты, с помощью которых вы читаете и проверяете файлы Portable Document Format (PDF), а также преобразуете их содержимое в структурированные данные. Она включает инспектор, валидаторы соответствия, менеджер PDF/A, контракты для импортированных объектов, контракты эмбеддингов и векторного индекса, а также подпространство имён валидатора электронных счетов.

Окно терминала
composer require nextpdf/core:^3

InspectorInterface читает необработанные байты PDF и возвращает структурированный InspectResult. Результат содержит перечень объектов в файле. Используйте этот контракт для любого инструмента, который читает PDF, созданный вне этого движка.

ExternalComplianceValidatorInterface связывает движок с внешним инструментом проверки, например veraPDF. Этот инструмент проверяет PDF/A и PDF/Universal Accessibility (PDF/UA). Если инструмент проверки не настроен, нулевая реализация возвращает результат “недоступно”. Сайт без veraPDF всё равно работает. ProfileValidatorInterface сверяет среду выполнения с профилем развёртывания, включая обязательные и рекомендуемые расширения. Он возвращает типизированный вердикт.

PdfAManagerInterface поддерживает соответствие файла PDF/A спецификации, пока писатель формирует файл. Он блокирует JavaScript, действия форм на JavaScript и встроенное шифрование. PDF/A запрещает все три механизма. Он также проверяет, что каждый шрифт внедрён, задаёт метаданные, соответствующие спецификации, и записывает необходимые объекты перед каталогом. Реальный класс поставляется в редакции Pro. Ядро находит его через class_exists() и приводит к типу контракта. В движке с открытым исходным кодом нет платных зависимостей.

Для импортированных объектов есть два контракта: ImportedFormObjectInterface и EmbeddedPdfObjectInterface. Они предоставляют типизированный доступ к объектам, прочитанным из существующего PDF, чтобы движок мог внедрить их повторно. Путь без потерь сохраняет необработанные байты словаря. Резервный путь предоставляет разобранный массив словаря для объектов, взятых из потоков объектов. Каждый повторно внедрённый объект является косвенным объектом PDF. Его идентифицируют номер объекта и номер поколения, как определено в ISO 32000-2 §7.3.10.

Контракты эмбеддингов поддерживают поиск. EmbeddingServiceInterface преобразует текст в плотный вектор и сообщает размерность и имя модели, чтобы вызывающий код мог адаптироваться во время выполнения. Редакция Pro выполняет модель на центральном процессоре (CPU). Редакция Enterprise выполняет модель на графическом процессоре (GPU). VectorIndexInterface строит индекс ближайших соседей и выполняет поиск по нему. Это небольшой внутрипроцессный индекс для использования в ядре. Поиск большего масштаба остаётся в контракте, доступном только в редакции Enterprise.

Группа EInvoice содержит межуровневый инструмент проверки электронных счетов. ValidatorInterface выполняет предварительные проверки полезной нагрузки Cross Industry Invoice (CII) или Universal Business Language (UBL). SchematronRunnerInterface выполняет проход по бизнес-правилам. ValidationResult фиксирует находки и нарушения правил. Инструмент проверки должен отклонять некорректный ввод, возвращая результат, а не выбрасывая исключение. Он также должен защищать от полезных нагрузок с объявлением типа документа (DOCTYPE) и чрезмерно больших полезных нагрузок.

ТипВидКлючевые членыСтабильностьС версии
InspectorInterfaceинтерфейсinspect(string, InspectConfig): InspectResultэкспериментальный2.2.0
ExternalComplianceValidatorInterfaceинтерфейсvalidate(string, ComplianceFlavour), isAvailable()экспериментальный2.4.0
ProfileValidatorInterfaceинтерфейсvalidate(DeploymentProfile): DeploymentProfileResultэкспериментальный2.4.0
PdfAManagerInterfaceинтерфейсvalidateNoJavaScript(), validateFont(), validateNoEncryption(), applyOutputProfile(), writeRequiredObjects()стабильный1.10.0
ImportedFormObjectInterfaceинтерфейсgetWidth(), getHeight(), getEmbeddedObjects(), getResourcesDict(), getMediaBox(), getContentStream()стабильный1.8.0
EmbeddedPdfObjectInterfaceинтерфейсgetRawDictionaryBytes(), getRawStreamData(), getDictionary()стабильный1.8.0
EmbeddingServiceInterfaceинтерфейсembed(), batchEmbed(), getDimension(), getModelName()экспериментальный2.1.0
VectorIndexInterfaceинтерфейсbuild(), search(), delete(), count()экспериментальный2.1.0
EInvoice\ValidatorInterfaceинтерфейсvalidate(string, ValidatorContext): ValidationResultэкспериментальный5.1.0
EInvoice\ValidationResultфинальный класс readonly$isValid, getErrors(), getWarnings(), fail()экспериментальный5.1.0

Пространство имён EInvoice также публикует SchematronRunnerInterface, ProfileInterface, ValidationFinding, RuleViolation и перечисления ProfileType, RuleSeverity и ValidationFindingLevel.

examples/contracts/extraction-quickstart.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\InspectorInterface;
use NextPDF\Inspect\InspectConfig;
/**
* Inspect a PDF and report its object count.
*
* @param InspectorInterface $inspector A configured inspector.
* @param string $pdfData Raw PDF bytes.
*/
function describe(InspectorInterface $inspector, string $pdfData): \NextPDF\Inspect\InspectResult
{
return $inspector->inspect($pdfData, new InspectConfig());
}

Эта функция зависит от контракта, поэтому ей подходит любая реализация инспектора.

examples/contracts/extraction-production.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../../vendor/autoload.php';
use NextPDF\Contracts\EInvoice\ValidatorInterface;
use NextPDF\Contracts\EInvoice\ValidatorContext;
use NextPDF\Contracts\ExternalComplianceValidatorInterface;
use NextPDF\ValueObjects\ComplianceFlavour;
use Psr\Log\LoggerInterface;
final readonly class InvoiceConformanceService
{
public function __construct(
private ValidatorInterface $invoiceValidator,
private ExternalComplianceValidatorInterface $pdfaValidator,
private LoggerInterface $logger,
) {}
/**
* Validate the invoice XML, then the PDF/A-3 carrier.
*
* @param string $xml The CII or UBL invoice payload.
* @param string $pdfPath Absolute path to the PDF/A-3 carrier.
*/
public function validate(string $xml, string $pdfPath, ValidatorContext $ctx): bool
{
$result = $this->invoiceValidator->validate($xml, $ctx);
if (!$result->isValid) {
$this->logger->warning('Invoice XML invalid', [
'errors' => \count($result->getErrors()),
]);
return false;
}
if (!$this->pdfaValidator->isAvailable()) {
$this->logger->info('PDF/A validator unavailable; skipping carrier check.');
return true;
}
$carrier = $this->pdfaValidator->validate($pdfPath, ComplianceFlavour::PdfA3b);
return $carrier->isConformant();
}
}

Этот сервис явно обрабатывает недоступный валидатор, а не предполагает, что валидатор всегда присутствует.

  • EInvoice\ValidatorInterface::validate() возвращает неуспешный ValidationResult для некорректного ввода. Он не выбрасывает исключение при нарушениях корректности. Проверяйте $isValid; не оборачивайте вызов в try/catch для этого случая.
  • ExternalComplianceValidatorInterface::isAvailable() необходимо проверить, прежде чем полагаться на вердикт. Нулевая реализация возвращает “недоступно”. Если трактовать это как “несоответствующий”, появятся ложноотрицательные результаты.
  • EmbeddedPdfObjectInterface::getRawDictionaryBytes() возвращает null для объектов, взятых из потока объектов. Используйте резервный вариант getDictionary(). Не предполагайте, что необработанные байты существуют.
  • EmbeddingServiceInterface::getDimension() различается по уровню редакции. Код, который выделяет вектор фиксированной ширины, должен читать размерность во время выполнения, а не задавать её жёстко.
  • VectorIndexInterface::build() требует списков векторов и идентификаторов одинаковой длины с согласованными размерностями. Несоответствие вызывает InvalidArgumentException. Проверяйте списки, прежде чем строить индекс.

Стоимость проверки и валидации растёт с размером документа и количеством объектов. performance_budget в 1500 ms по времени выполнения и 64 MB по пику покрывает один документ умеренного размера. Внешний вызов veraPDF добавляет время выполнения отдельного процесса. Это время находится вне бюджета движка, и вызов следует выносить из пути запроса. Стоимость эмбеддинга растёт с длиной текста; пакетная обработка гораздо дешевле цикла, особенно на модели GPU. Предпочитайте batchEmbed(). Векторный поиск сублинеен по размеру индекса для внутрипроцессного индекса. Профиль воспроизводимости — structural. Отчёт о валидации фиксирует метку времени и отпечаток среды. Из-за этих полей два запуска различаются, тогда как вердикт о соответствии остаётся идентичным.

Извлечение читает документы, созданные не этим движком, поэтому любой ввод считается недоверенным. И инспектор, и валидатор электронных счетов разбирают байты, предоставленные извне. Валидатор электронных счетов должен блокировать полезные нагрузки с объявлением типа документа (DOCTYPE), чрезмерно большие полезные нагрузки и полезные нагрузки с запрещёнными управляющими символами до разбора, чтобы предотвратить атаки через внешние сущности Extensible Markup Language (XML) и атаки billion-laughs. Повторное внедрение импортированных объектов копирует байты из стороннего PDF. Вредоносный исходный объект может нести враждебное содержимое, поэтому повторное внедрение сохраняет байты и не выполняет их. Принудительное применение PDF/A удаляет JavaScript и действия. Менеджер PDF/A отклоняет JavaScript и шифрование, поскольку оба запрещены профилем и оба являются векторами злоупотребления в долгоживущем архивном документе. Относитесь к проверяемому содержимому, импортированным объектам и XML счёта как к враждебному вводу на всём протяжении.

УтверждениеСтандартПунктПодтверждение
PDF/A-4 запрещает JavaScript и действия форм на JavaScript; менеджер PDF/A отклоняет оба.ISO 19005-4§6.7.1процитировано по пункту (нет в корпусе)
Каждый повторно внедрённый объект является косвенным объектом PDF, идентифицируемым номером объекта и поколением.ISO 32000-2§7.3.10

ISO 19005-4 цитируется по пункту. Его нет в корпусе проверяемых цитат, поэтому reference_id не записывается. Утверждение о косвенном объекте по ISO 32000-2 закреплено в глоссарии. Оба утверждения приведены в пересказе. Движок не воспроизводит нормативный текст.

Ядро определяет и фиксирует контракты извлечения. Продакшен-код за PdfAManagerInterface, EmbeddingServiceInterface и VectorIndexInterface поставляется в редакциях Pro и Enterprise, включая модели эмбеддинга на CPU и GPU и полный путь принудительного применения PDF/A. Ядро разрешает их во время выполнения через class_exists(). Поэтому движок с открытым исходным кодом не несёт коммерческих зависимостей, а API не меняется при обновлении.