PDF 要么符合 PDF/A-3,要么不符合。既然标准答案只有一个,为什么还要对同一个文件跑两个验证器?
原因很现实:PDF/A 规范足够庞大,两个认真实现的验证器仍可能在边界条件上给出不同判断。在审计、归档、电子发票这些场景里,单一引擎显示 “Pass” 更像黄灯,不是可以直接放行的绿灯。
PDF/A 不是一个简单算法
PDF/A 横跨 ISO 19005 的多个版本,PDF/A-1、PDF/A-2、PDF/A-3、PDF/A-4 又各自有 b、a、u、e、f 等不同符合级别。它们还叠加在 PDF 本体规范 ISO 32000 之上。实际要解释的规范文本是数千页级别。
常见分歧通常发生在这些地方:
- PDF/A-2/3 里的透明度:标准允许特定条件下使用,但条件判断并不总是机械清晰。
- ICC 色彩配置:某个 profile 到底是必须还是建议,不同实现可能给出不同结论。
- PDF/A-3 附件元数据:
AFRelationship、/AF引用、XMP 元数据都要对齐,严格程度会影响结果。 - 字体子集:CID 字体、部分嵌入和真实编码之间的边界尤其容易暴露实现差异。
这些不一定是某个验证器的 bug,而是复杂规范由不同团队独立实现后的自然结果。越是受监管行业,越倾向要求多一次独立确认。
参考实现之外,还需要第二意见
veraPDF 是 PDF Association 维护的参考实现,也是 PDF/A 验证里最重要的单一信号。如果 veraPDF 通过,说明文件已经过了最权威的一关。
但“最强单一信号”仍不等于“审计级证据”。银行、医疗档案、政府记录和长期归档系统通常希望看到第二个独立引擎,因为:
- 下游系统可能使用另一个验证器,单引擎通过不代表一定不会被拒收。
- 任何单一实现都可能有 bug,重复跑同一个引擎无法发现它。
- 合规采购里常见的原则是“两份独立确认”,PDF/A 只是继承了这种工作方式。
gPdf 的做法是把 veraPDF 与我们自己的 Rust + WebAssembly 验证引擎放在一起。后者是对同一套规范的独立实现。两个引擎都通过时,证据强度明显高于任意一个单独结果;两个引擎不一致时,也能快速定位需要检查的字段或实现差异。
一个 URL 同时看两份报告
我们把这个流程做成了免费的 gpdf.com/validator/:无需登录,上传文件后同时跑 veraPDF 和 gPdf edge engine,并把两份报告并排返回。
典型用法很直接:
- 准备交付 PDF/A 文件:上传、双引擎通过,把 JSON 报告作为 QA 证据留档。
- 一个通过、一个失败:对比报告,通常能找到 XMP 时间、
/AF引用或附件关系这类细节问题。 - 两个都失败:文件本身不合规,应回到生成源头修复。
- 抽检归档批次:随机抽样上传,把报告 URL 和结果放进审计底稿。
上传的文件只在请求内存中处理。验证在 Cloudflare Workers 上完成,报告生成后文件即被丢弃;无需登录、无需持久化、无需配额。
这种模式也适用于电子发票
双重确认并不只适用于 PDF/A。Factur-X / ZUGFeRD 电子发票同样需要同时确认 PDF/A-3 外壳和嵌入的 EN 16931 CII XML。gPdf 的 validator 会结合 Mustang 对发票 XML 做检查,再与 PDF/A 报告一起展示。
这就是合规世界长期采用的模式:不是相信某个单点工具,而是让两个独立实现给出同一结论。
TL;DR
单引擎 “Pass” 是黄灯;双引擎 “Pass” 才更接近绿灯。把文件丢到 validator,拿到 veraPDF 和 gPdf 两份报告,再把它们作为 QA 或审计证据。使用 gPdf API 生成的 PDF,也可以通过这个公开验证器证明合规声明确实被兑现。