跳到內容

產生 PDF/A-4 封存用輸出

這份 recipe(範例)使用 Pro 的 PdfAManager 產生 PDF/A-4(ISO 19005-4)封存用輸出。儲存時,NextPDF 會排程 OutputIntent、內嵌的 ICC 描述檔以及識別中繼資料。NextPDF 產生的是力求符合一致性的輸出;最終是否一致,則由獨立驗證器判定。這份 recipe 依循 examples/32-pdfa4-icc.php

Terminal window
composer require nextpdf/core:^3
composer require nextpdf/pro

PDF/A-4 是 Pro 等級的功能。在僅安裝核心套件的環境中,enablePdfA() 會擲出 InvalidConfigException。訊息會指出缺少的 security.pdfa 能力,並提示以 composer require nextpdf/pro 修正。驗證步驟需要 PATH 中有一個 PDF/A 驗證器。範例使用以 --flavour 4 執行的 veraPDF。

PDF/A-4 是建構在 ISO 32000-2(PDF 2.0)之上的 ISO 19005-4 封存設定檔。符合一致性的檔案具有確定的色彩表現,且能自我完備。它會宣告一個 OutputIntent,並參照一個內嵌的 ICC 目標描述檔,讓色彩不需外部資源即可重現(§6.2.3)。每個字型程式都會被內嵌(§6.2.10.4.1)。文件會在 XMP 中帶有 pdfaid 識別中繼資料(§6.7.3)。檔案會加密(§6.6.4 —— PDF/A 禁止使用 Encrypt trailer 鍵)。

NextPDF 以具型別的 ConformanceMode enum 來建模 PDF/A。enablePdfA() 會實例化 Pro 的 PdfAManager,預設使用 ConformanceMode::PdfA4。這個管理器會在 save() 期間排程 OutputIntent、ICC 串流與 XMP 擴充結構描述。pdfaPart()pdfaConformanceLetter() 這兩個鑑別子會讓 pdfaid:part / pdfaid:conformance 中繼資料,與所選變體(基本款 44e4f)保持一致。依該部分要求,基本設定檔不會輸出 pdfa:conformance 字母。

此 API 介面由 PHPDoc 產生。主要進入點:

  • \NextPDF\Core\Document::createStandalone(): Document
  • Document::enablePdfA(?object $version = null): static
  • \NextPDF\Support\CapabilityRegistry::getInstance()->get('security.pdfa')->isAvailable(): bool
  • \NextPDF\Conformance\ConformanceMode::PdfA4 / PdfA4e / PdfA4f
  • ConformanceMode::pdfaPart(): 2|3|4|nullConformanceMode::pdfaConformanceLetter(): string
examples/32-pdfa4-icc.php
<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Core\Document;
use NextPDF\Support\CapabilityRegistry;
$out = __DIR__ . '/output/32-pdfa4-icc.pdf';
// Probe before activating a Pro-gated feature so a Core-only install
// gets an actionable message instead of a stack trace.
$registry = CapabilityRegistry::getInstance();
if (!$registry->get('security.pdfa')->isAvailable()) {
fwrite(STDERR, "PDF/A-4 requires nextpdf/pro. Run: composer require nextpdf/pro\n");
exit(1);
}
$doc = Document::createStandalone();
$doc->enablePdfA(); // defaults to ConformanceMode::PdfA4
$doc->setTitle('Archival Record 2026-0042');
$doc->setLanguage('en');
$doc->addPage();
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 10, 'This document targets PDF/A-4.', newLine: true);
$doc->save($out); // PdfAManager emits OutputIntent + ICC + XMP here
echo "Created: output/32-pdfa4-icc.pdf\n";

這是一支自我完備、可由測試載具執行的程式。正式環境的呼叫端會將驗證器的判定當成建構 gate。成功的 save() 只能證明 NextPDF 已輸出這些成品;只有驗證器才能證明一致性。

<?php
declare(strict_types=1);
require_once __DIR__ . '/vendor/autoload.php';
use NextPDF\Core\Document;
use NextPDF\Exception\InvalidConfigException;
use NextPDF\Support\CapabilityRegistry;
$out = getenv('NEXTPDF_COOKBOOK_OUTPUT') ?: (__DIR__ . '/archival.pdf');
if (!CapabilityRegistry::getInstance()->get('security.pdfa')->isAvailable()) {
fwrite(STDERR, "PDF/A-4 requires nextpdf/pro. Run: composer require nextpdf/pro\n");
exit(1);
}
try {
$doc = Document::createStandalone();
$doc->enablePdfA(); // ConformanceMode::PdfA4
$doc->setTitle('Archival Record 2026-0042');
$doc->setLanguage('en');
$doc->addPage();
$doc->setFont('helvetica', '', 12);
$doc->cell(0, 10, 'Long-term archival record. PDF/A-4 (ISO 19005-4).', newLine: true);
// Do NOT call setEncryption(): PDF/A prohibits the Encrypt key and
// the call raises an incompatibility exception in either order.
$doc->save($out);
} catch (InvalidConfigException $e) {
fwrite(STDERR, "PDF/A-4 activation failed: {$e->getMessage()}\n");
exit(1);
}
$exitCode = 0;
$report = [];
exec('verapdf --flavour 4 ' . escapeshellarg($out), $report, $exitCode);
if ($exitCode !== 0) {
fwrite(STDERR, "veraPDF FAILED — output is not PDF/A-4 conforming\n");
fwrite(STDERR, implode("\n", $report) . "\n");
exit(1);
}
echo "veraPDF PASS — archival.pdf is reported PDF/A-4 conforming\n";

在已安裝 nextpdf/pro、且 verapdf 回報檔案符合一致性的主機上,預期的 STDOUT 為:

veraPDF PASS — archival.pdf is reported PDF/A-4 conforming

在僅有核心套件的主機上,程式會在 STDERR 印出 PDF/A-4 requires nextpdf/pro. Run: composer require nextpdf/pro 後,以非零碼結束。若 verapdf 回報有問題,程式會在印出 veraPDF FAILED — output is not PDF/A-4 conforming 後,以非零碼結束。這裡的措辭將判定歸於 veraPDF —— NextPDF 並不主張 PDF/A-4 一致性。

  • **Pro gate。**在僅有核心套件的環境中,enablePdfA() 會擲出 InvalidConfigException。訊息會指出 security.pdfa,並提示以 composer require nextpdf/pro 修正。先探查登錄表,才能取得清楚的操作人員訊息。
  • **加密衝突。**在 PDF/A 文件上呼叫 setEncryption()useAesGcm()setPublicKeyEncryption(),無論呼叫順序為何都會擲出不相容例外 —— PDF/A-4 禁止使用 Encrypt trailer 鍵(ISO 19005-4 §6.6.4)。
  • **一致性變體。**把 Pro 的 PdfAVersion 傳給 enablePdfA(),即可選擇 4e(工程、3D)或 4f(檔案附件)。基本設定檔不會輸出 pdfa:conformance 字母;4e/4f 則會設定 E/FConformanceMode 鑑別子會讓 pdfaid:part 維持一致。
  • **標記是獨立的。**PDF/A-4 基本款把標記視為選用。若要同時兼顧無障礙封存的交付物,請分別啟用標記模式與 PDF/A;請參閱 PDF/UA-2 的 recipe。
  • **gate 是驗證器。**成功的 save() 只代表成品已輸出,並不代表檔案符合一致性。在驗證器通過之前,不要聲稱符合 PDF/A-4 一致性。

OutputIntent 會增加一個 ICC 描述檔串流(sRGB 約數百 KB),外加 XMP 封包。當文件使用非基本 14 字型時,字型內嵌會成為檔案大小的主要來源。對於典型的封存文件,這份 recipe 會維持在 2000 ms / 128 MB 的預算內。適用的語意可重現性設定檔:以驗證器為導向的交付物會以結構化 AST 加上中繼資料來比較,而非原始位元組。

封存輸出的設計目標就是長期保存且自我完備。內容中的任何個人資料都會在封存的存續期間持續存在。內嵌的 ICC 描述檔與中繼資料會隨檔案一同流通。封存前請套用保存與最小化政策。PDF/A-4 不具備遮蔽(redaction)語意。

這份 recipe 只會寫出一行固定的進度訊息。veraPDF 的輸出可能包含內容片段;對於含有敏感內容的文件,請避免將驗證器日誌送入共用的日誌彙整端。

PDF/A-4 是封存保真度設定檔,並不是完整性或真實性控制。它不會替檔案簽章,也不會提供竄改跡證。若在意 provenance(來源資訊),請搭配簽章使用。另有一份 recipe 涵蓋簽章。依規格而言,加密與 PDF/A 互斥。

這份 recipe 不會執行任何密碼學運算。FIPS 模式不會改變其行為。PDF/A-4 禁止加密,因此不會選擇任何密碼演算法。

陳述規格條款參考 ID
PDF/A-4 要求一個 OutputIntent,並參照一個內嵌的 ICC 描述檔。ISO 19005-4§6.2.3
輸出目標描述檔讓色彩與裝置無關。ISO 19005-4§6.2.4.3
每個字型程式都會被內嵌。ISO 19005-4§6.2.10.4.1
文件會在 XMP 中帶有 pdfaid 識別資訊。ISO 19005-4§6.7.3
PDF/A-4 禁止加密。ISO 19005-4§6.6.4
由驗證器而非產生器來判定一致性。ISO 19005-4§6.7.3

NextPDF 產生的是力求符合 PDF/A-4 一致性的輸出。**支援不等於一致;經測試的設定檔不等於認證。**這份 recipe 並不主張一致性;該判定由獨立驗證器(例如 veraPDF)作出。請把驗證器判定當成建構 gate。