跳到內容

剖析並檢視 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,而且可離線執行。