跳转到内容

归档与 PDF/A

Spec: ISO 19005-4:2020, PDF/A-4 Spec: ISO 19005-2, PDF/A-2 Evidence: Standard-backed

PDF/A 是当一份文件必须在数十年后、在尚不存在的软件上仍然可读且忠实重现时,你会采用的格式。本页说明这项保证实际涵盖什么、NextPDF 如何生成一份符合规范的文件,以及经常让团队感到意外的那一部分。生成 PDF/A,以及 证明一份文件确实是 PDF/A,是两件不同的事。后者仍然是你的责任。

归档义务往往以一种无声的方式变得毫不宽容。文件在今天看起来没问题,于是被归档。而问题——未内嵌的字体、依赖设备的色彩、加密过的尾段——往往多年后才暴露出来;那时原始环境已不复存在,也没有人能重建这份文件本应呈现的样子。到那时,代价就不只是重新渲染一次,而是一条你再也无法信任的记录。

PDF/A 之所以存在,正是为了消除这类失败。但“我们用了一套 PDF/A 库”并不等同于“这份文件符合规范”。把两者混为一谈, 正是归档库中不断累积那些只是看起来已被保存的文件的原因。

  • PDF/A 的目的,是让文件能随着时间推移,以忠实、自足且与设备无关的方式重现——它保存一份文件的静态视觉外观,并独立于制作该文件的工具之外(ISO 19005-2 导论)。
  • 这需要具体约束:所有字体都要内嵌与设备无关的色彩(直接指定,或通过输出意图;ISO 19005-4 §6.2.4.1),以及尾段中不得加密
  • NextPDF 通过一个明确、需主动启用的模式来生成 PDF/A,该模式会拒绝不兼容的操作,而不是交出一份悄然不符合规范的文件。
  • 符合性由检核工具判定,而不是由生成器宣称。 即便标准本身能够成功发挥作用,也取决于周边的归档环境与流程(ISO 19005-4 导论)。验证输出结果,是你仍然必须完成的一步。

NextPDF 将 PDF/A 视为文件所处的一种模式,而不是后处理过滤器。这个模式需要主动启用。一旦启用,它就会主动守护文件,防止任何会破坏符合性的操作。其设计原则是快速失败。与其返回一份看似可归档、实际并不符合要求的文件,不如明确拒绝一个加密的 PDF/A 要求。

这个场景有四个阶段,而第三个正是团队经常略过的那一步。

  1. Compose for permanence Embed every font, use device-independent colour or an output intent, and avoid features the chosen PDF/A part forbids.
  2. Enable the PDF/A mode Opt in explicitly to the target conformance level. The mode now guards the document against incompatible operations.
  3. Validate independently Run a conformance checker. A passing report — not the producing library — is the evidence the archive needs.
  4. Preserve with procedure Store under records-management policy. The standard itself notes archival success depends on the environment, not the file alone.
从头到尾的封存情境:引擎产生一份符合规范的候选档,并拒绝会破坏符合性的操作;由独立的验证器交出对封存而言真正重要的裁定。

这个主动启用是一道真正的防护,而不只是一个标志。当 PDF/A 模式已启用,却又尝试执行不兼容的操作时——例如开启 AES-GCM 或标准加密处理器——引擎会抛出一个具类型的不兼容错误。这道防护在两种顺序下都有效:先启用 PDF/A 再要求加密,或先要求加密再启用 PDF/A。无论是哪一种,结果都是明确拒绝。 ISO 19005 禁止在符合规范的文件尾段中出现 Encrypt 密钥, 而引擎将此视为有约束力的要求,而不是仅供参考的提示。

这个模式也会让自身状态保持诚实。为某个特定部分启用 PDF/A(例如选择字节忠实层级的 PDF/A-3 而非 PDF/A-4)时,它会把文件的符合性判别值设为相符。凡是依赖该部分的写入端关卡,都会看到正确的值,而不是过时的默认值。正是这种内部一致性,决定了验证器是否会让这份文件通过。

本页通篇都有标准佐证 Evidence: Standard-backed

目的由标准所固定。 Spec: ISO 19005-2 指出 PDF/A 的主要目的是提供一套用于表述电子文件的机制,使其静态视觉外观能够随时间保存,并独立于所使用的工具与系统之外。 而约束也由此衍生: Spec: ISO 19005-4:2020, §6.2.4.1 要求色彩须以与设备无关的方式指定,可以直接指定,也可以通过 PDF/A 输出意图。 字体要求则由基础格式进一步强化—— Spec: ISO 32000-2:2020, §9 指出,最可预期、 最可靠的渲染发生在所有字体都已内嵌时,而这正是归档库不可或缺的性质。

这个边界同样写在标准里,而不只是编辑上的告诫。 Spec: ISO 19005-4:2020 在其导论中指出, 面向归档目的的成功实现,取决于组织的归档环境、记录管理政策,以及其他持久保存条件。符合性由检核工具依据标准的规范性要求来判定——而不是由生成器宣告。

引擎的行为则为代码佐证 Evidence: Code-backed Document::enablePdfA() 是一个明确的主动启用操作;当加密与 PDF/A 以任一顺序组合在一起时,它都会抛出一个具类型的不兼容错误, 并让文件的符合性判别值与所选部分保持同步一致。

下方代码展示了边界处的防护行为。其中 PDF/A 模式本身属于 Premium 层级的功能。 而符合性检核则是一道独立且分离的步骤。

<?php
declare(strict_types=1);
use NextPDF\Contracts\PdfDocumentInterface;
use NextPDF\Security\Exception\IncompatiblePdfAModeException;
/**
* Produce an archival candidate, then prove it independently.
*
* The engine refuses conformance-breaking combinations; it does NOT
* certify the result. A validator does that.
*
* @param PdfDocumentInterface $doc A document with all fonts embedded
* @param object $pdfaLevel The target PDF/A version (Premium enum)
*
* @return string The archival candidate's bytes — not yet a verified PDF/A
*/
function buildArchivalCandidate(
PdfDocumentInterface $doc,
object $pdfaLevel,
): string {
try {
// Opt in explicitly. From here the mode guards the document.
$doc->enablePdfA($pdfaLevel);
} catch (IncompatiblePdfAModeException $e) {
// e.g. encryption was already requested — refused, not silently
// downgraded into a non-conforming "archival" file.
throw new \RuntimeException(
'PDF/A and encryption are mutually exclusive for a conforming '
. 'file; resolve before archiving.',
previous: $e,
);
}
$bytes = $doc->getPdfData();
// The step teams skip: this is a CANDIDATE. Run an independent
// conformance validator before treating it as a preserved record.
return $bytes;
}

返回值上的那行注释,正是这里的重点。函数名称刻意使用了候选(candidate)这个词。引擎产出的是某个应当符合规范的结果。只有检核工具,才能把“应当”变成证据。

有一个误解会让归档库塞满并未真正保存下来的文件:“库说它是 PDF/A,所以这份文件就是 PDF/A。” 但这个裁定并非库能够给出。一个生成器可以产出一份意图符合规范的文件,却仍然漏掉某项规范性要求。符合性由验证工具依标准判定。审核人员或未来读者所依赖的,正是那项判定。把生成库的意图当成证明,正是这里的核心错误。

第二个更隐蔽的陷阱:以为只靠 PDF/A 就能保存文件。标准本身就把归档成功系于周边环境与流程。一份符合规范的文件,如果位于缺乏纪律的存储库中,仍然处于风险之中。这个格式是必要的,但并不充分。

  • NextPDF 生成的是一份符合规范的候选文件;它并不认证符合性。 请执行一个独立的验证器。通过的报告才是证据,而不是那个生成库。
  • PDF/A 的符合性模式属于 Premium 层级的功能。 Core 产出纯粹的 PDF 2.0,并提供一条可执行的升级路径。它不提供 PDF/A 保证。请参阅下方的边界说明。
  • PDF/A 与加密,对一份符合规范的文件而言是互斥的。 引擎会以任一顺序拒绝这种组合,而不是悄然降级。
  • 引擎无法内嵌未提供给它的字体,也无法修正你提供的、依赖设备的色彩。 为了永久保存而进行编排——内嵌字体、与设备无关的色彩——是输入端的责任。
  • 归档的持久性取决于流程,而不是仅靠文件本身。 ISO 19005 把组织的留存与记录管理流程纳入成功保存的一部分。
  • 本页在 Premium 范围内属于标准佐证、行为层级的内容。它不主张任何认证,也不授予任何认证。
PDF/A archival conformance — edition availability
Edition Availability
Core

Core 只产出纯粹的 PDF 2.0。 enablePdfA() 会抛出一个可执行的升级错误,指向商业套件。不存在仅靠 Core 提供的 PDF/A 保证。

Pro

提供 PDF/A 符合性模式(包括字节忠实的 PDF/A-3 层级与 PDF/A-4),并附带加密不兼容防护。

Enterprise

增加一套结构化的 PDF/A 符合性政策与报告(仍然是一项结构检核,而不是认证——最终判定属于验证器与你的合规团队)。

  • 字体:最难的部分——为什么一个看起来正确的字体,仍可能让文件不符合规范或无法搜索。
  • 黄金文件测试——固定参考输出如何捕捉那些悄然破坏归档保证的字节偏移。
  • 发票与电子发票——最相近的邻居:一个混合式发票载体本身就是一份 PDF/A 文件。
  • PDF/A——ISO 19005 系列:一套用于长期保存的受限 PDF 配置文件,设计用来随着时间推移重现一份文件的静态外观,并独立于生成它的工具之外。
  • 符合性层级/部分——特定的 PDF/A 变体(例如 PDF/A-2PDF/A-3PDF/A-4 及其子层级);各自约束哪些 PDF 功能可以使用。
  • 输出意图——一个内嵌的色彩特性化配置文件,让依赖设备的色彩能以与设备无关的方式被解读。
  • 与设备无关的色彩——以某种方式指定的色彩,使其无论在何种渲染设备上都能一致重现,这是 PDF/A 的要求。
  • 符合性检核器/验证器——独立软件,依据标准的规范性要求评判一份文件;它是符合性裁定的来源。
  • 归档候选文件——一份按意图生成、应当符合规范的文件,在独立验证器确认它确实符合之前。