Разбор PDF и проверка структурных сведений
В этом рецепте резервный режим Quick в инспекторе Core читает структурные сведения из файла Portable Document Format (PDF). В результате вы получаете версию, число страниц, флаги шифрования, подписи и вложений, размер файла и флаги риска. Режим Quick работает полностью внутри процесса: без сопроцесса Spectrum и без доступа к сети. Используйте его для быстрой сортировки, а не как валидатор.
Установка
Заголовок раздела «Установка»composer require nextpdf/core:^3Концептуальный обзор
Заголовок раздела «Концептуальный обзор»В PDF-файле версия указана в заголовке файла (ISO 32000-2 §7.5.2). Трейлер содержит идентификатор файла (/ID) в виде двух байтовых строк (ISO 32000-2 §7.5.5). При наличии подписи словарь подписи хранит структуру Cryptographic Message Syntax (CMS) SignedData в кодировке Distinguished Encoding Rules (DER) в Contents (ISO 32000-2 §12.8.1). Резервный режим Quick выполняет ограниченное сканирование байтов документа, чтобы определить версию, оценить число страниц и выставить флаги наличия шифрования, подписи и вложений.
Поверхность API
Заголовок раздела «Поверхность API»Создайте new Inspector(), затем вызовите ->inspect(string $pdfData, InspectConfig::quick()). Метод возвращает InspectResult с полями $pdfVersion, $pageCount, $isEncrypted, $hasSigned, $hasAttachments, $fileSizeBytes, $riskFlags и вспомогательным методом hasRisks().
Пример кода — быстрый старт
Заголовок раздела «Пример кода — быстрый старт»<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Inspect\InspectConfig;use NextPDF\Inspect\Inspector;
$pdf = file_get_contents(__DIR__ . '/document.pdf');$result = (new Inspector())->inspect($pdf, InspectConfig::quick());
printf( "v%s, %d page(s), encrypted=%s, signed=%s\n", $result->pdfVersion ?? '?', $result->pageCount, $result->isEncrypted ? 'yes' : 'no', $result->hasSigned ? 'yes' : 'no',);Пример кода — продакшен
Заголовок раздела «Пример кода — продакшен»Эта самодостаточная программа выполняется в среде запуска рецептов. Она повторяет examples/39-parse-and-inspect-pdf.php: строит небольшой многостраничный PDF в памяти, считывает его структурные сведения в резервном режиме Quick и маршрутизирует документ по этим сведениям, но никогда не по вердикту доверия. Ветвь маршрутизации приведена для иллюстрации. Замените её собственным конвейером, очередью верификации и карантином.
<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;use NextPDF\Inspect\InspectConfig;use NextPDF\Inspect\Inspector;
// A self-contained input so the program runs with no external file.$doc = Document::createStandalone();$doc->setTitle('Parse-and-inspect demo');$doc->setAuthor('NextPDF Cookbook');$doc->addPage();$doc->setFont('helvetica', '', 12);$doc->cell(0, 10, 'Page one of the parse-and-inspect demonstration.', newLine: true);$doc->addPage();$doc->cell(0, 10, 'Page two.', newLine: true);$pdf = $doc->getPdfData();
$result = (new Inspector())->inspect($pdf, InspectConfig::quick());
echo 'PDF version : ' . ($result->pdfVersion ?? 'unknown') . "\n";echo 'Pages : ' . $result->pageCount . "\n";echo 'Encrypted : ' . ($result->isEncrypted ? 'yes' : 'no') . "\n";echo 'Signed : ' . ($result->hasSigned ? 'yes' : 'no') . "\n";echo 'Attachments : ' . ($result->hasAttachments ? 'yes' : 'no') . "\n";echo 'File size : ' . $result->fileSizeBytes . " bytes\n";echo 'Risk flags : ' . ($result->hasRisks() ? count($result->riskFlags) : 0) . "\n";
// Route on structural facts, not trust verdicts. Replace these calls with// your own pipeline / verifier queue / quarantine.if ($result->isEncrypted) { // $pipeline->decryptThenContinue($pdf); echo "Route: decrypt-then-continue\n";} elseif ($result->hasSigned) { // $verifierQueue->enqueue($pdf); // see the signature-inspect recipe echo "Route: enqueue for cryptographic verification\n";} elseif ($result->hasRisks()) { // $quarantine->hold($pdf, $result->riskFlags); echo "Route: quarantine (risk flags present)\n";} else { // $pipeline->continue($pdf); echo "Route: continue (no risks, unsigned, unencrypted)\n";}
// The harness sets NEXTPDF_COOKBOOK_OUTPUT and runs this script under the// semantic profile; emit the document to the side-channel.$out = getenv('NEXTPDF_COOKBOOK_OUTPUT');file_put_contents($out !== false && $out !== '' ? $out : __DIR__ . '/inspected.pdf', $pdf);Ожидаемый стандартный вывод (STDOUT): версия и размер зависят от сборки; демонстрационный PDF не зашифрован, не подписан и не содержит флагов риска:
PDF version : <version>Pages : 2Encrypted : noSigned : noAttachments : noFile size : <n> bytesRisk flags : 0Route: continue (no risks, unsigned, unencrypted)Граничные случаи и подводные камни
Заголовок раздела «Граничные случаи и подводные камни»- Quick — это сортировка, а не проверка. Он сообщает, что присутствует, а что отсутствует. Он не проверяет подписи, не расшифровывает содержимое и не подтверждает соответствие. Рассматривайте результат как входные данные для маршрутизации.
- Число страниц — это оценка. Резервный режим Quick подсчитывает маркеры объектов-страниц. Намеренно искажённый граф объектов может дать неверный подсчёт. Когда нужен точный подсчёт, используйте уровни глубины на основе Spectrum.
- Уровням Standard/Full нужен сопроцесс.
new InspectConfig()(глубинаStandard) иInspectConfig::full()требуют сопроцесса Spectrum. Когда он недоступен, они выбрасываютINSPECT-SIDECAR-001и не переключаются молча на Quick. - Пустые входные данные. При передаче пустой строки выбрасывается исключение проверки с сообщением “PDF data must not be empty”.
- Область действия флага шифрования. Флаг отражает наличие записи
/Encryptв трейлере. Инспектор не расшифровывает файл, помеченный этим флагом.
Производительность
Заголовок раздела «Производительность»Резервный режим Quick применяет ограниченное сканирование, а не полный разбор. Используйте его для предварительной маршрутизации больших объёмов входящих файлов перед более ресурсоёмкой обработкой.
Заметки по безопасности
Заголовок раздела «Заметки по безопасности»Инспектор выполняется внутри процесса и читает только структурные маркеры. Ни один байт документа не покидает хост, и текст документа не извлекается. Флаг риска, например наличие встроенного JavaScript, — это рекомендательный сигнал для маршрутизации. Это не утверждение о том, что файл безопасен или небезопасен.
Соответствие
Заголовок раздела «Соответствие»| Утверждение | Спецификация | Пункт | reference_id (идентификатор ссылки) |
|---|---|---|---|
| В заголовке файла записана версия PDF. | ISO 32000-2 | §7.5.2 | |
Запись трейлера /ID — это идентификатор файла из двух байтовых строк. | ISO 32000-2 | §7.5.5 | |
Запись Contents в словаре подписи содержит структуру SignedData в формате DER CMS. | ISO 32000-2 | §12.8.1 |
Этот рецепт сообщает только структурные сведения. Он не утверждает, что файл корректен, безопасен или соответствует требованиям.
Коммерческий контекст
Заголовок раздела «Коммерческий контекст»Уровни глубины проверки Standard и Full выполняются через сопроцесс Spectrum. Они добавляют более детальный анализ объектов, шрифтов и изображений. Описанный здесь резервный режим Quick относится к Core и работает офлайн.