跳转到内容

解析并查看 PDF 的结构性事实

本 recipe(示例)使用 Core 检视器的 Quick 后备机制,从 PDF 中读取结构性事实。这些事实包括版本、页数、加密标志、签名标志、附件标志、文件大小,以及风险标志。Quick 完全在进程内执行,不需要 Spectrum sidecar,也不联网。请将它用于快速初步分流,而不要把它当作验证器。

Terminal window
composer require nextpdf/core:^3

PDF 会把版本记录在文件头(ISO 32000-2 §7.5.2)。trailer 中包含一个由两个 byte 字符串组成的文件标识符(/ID)(ISO 32000-2 §7.5.5)。存在签名时,对应的是一个签名字典,其 Contents 存放 DER 编码的 CMS SignedData(ISO 32000-2 §12.8.1)。Quick 后备机制会通过对文件字节进行有界扫描,推导出版本、页数估计值,以及加密、签名与附件是否存在的标志。

先调用 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',
);

这是一段可独立执行、可在 harness 中运行的程序。它对应 示例 examples/39-parse-and-inspect-pdf.php:该示例会在内存中创建一份小型多页 PDF,用 Quick 后备机制读出它的结构性事实,再根据这些事实进行路由(而不是根据信任判定)。这些路由分支仅用于示意。请接入你自己的 pipeline、验证器队列与隔离区。

<?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 : 2
Encrypted : no
Signed : no
Attachments : no
File size : <n> bytes
Risk flags : 0
Route: continue (no risks, unsigned, unencrypted)
  • Quick 是初步分流,而非验证。 它报告哪些内容存在、哪些内容缺失。它不会验证签名、不会解密内容,也不会断言合规性。请将结果作为路由输入。
  • 页数是估计值。 Quick 后备机制计算的是页面对象标记的数量。刻意构造的畸形对象图可能让这个数字失准。需要精确页数时,请改用由 Spectrum 支撑的检视深度。
  • Standard/Full 需要 sidecar。 new InspectConfig()(深度 Standard)与 InspectConfig::full() 都需要 Spectrum sidecar。sidecar 不可用时,它们会抛出 INSPECT-SIDECAR-001,且不会静默降级为 Quick。
  • 空输入。 空字符串会抛出 inspect 异常,消息为「PDF data must not be empty」。
  • 加密标志的范围。 这个标志反映的是 trailer 中的一个 /Encrypt 项目。检视器不会解密被标记的文件。

Quick 后备机制是一次有界扫描,而不是完整解析。它适合在执行更重的处理之前,对大量传入文件进行高吞吐的前置路由。

检视器在进程内运行,只读取结构性标记。没有任何文件字节离开主机,也不会提取任何文件文本。风险标志(例如内嵌的 JavaScript)是供路由参考的提示性信号。它并不等于断言该文件安全或不安全。

陈述规范条款参考 ID
文件头会记录 PDF 版本。ISO 32000-2§7.5.2
trailer 的 /ID 是一个由两个 byte 字符串组成的文件标识符。ISO 32000-2§7.5.5
签名字典的 Contents 存放 DER 编码的 CMS SignedData。ISO 32000-2§12.8.1

本 recipe 报告的是结构性事实。它并不断言该文件有效、安全或符合规范。

Standard 与 Full 检视深度通过 Spectrum sidecar 执行。这些深度会加入更丰富的对象、字体与图像分析。这里记录的 Quick 后备机制属于 Core,而且可离线执行。