跳转到主内容
新派编程网 - 新潮编程理念,全新技术课堂!

C# 生成PDF/A文件 C#如何创建用于长期归档的PDF/A标准文件

PDF/A是ISO 19005定义的归档标准,要求字体嵌入、禁加密、禁JS、明确定义颜色空间和元数据;C#默认生成的PDF不满足这些强制约束,需用iText7.4.0+显式配置PDF/A合规性。 PDF/A 是什么,为什么 C# 默认生成的 PDF 不是 PDF/A PDF/A 不是“带 A 的 PDF”,而是 ISO 标准(ISO 19005)定义的一类严格归档格式:所有字体必须嵌入、禁止加密、禁用 JavaScript、颜色空间需明确指定、元数据必须完整。C# 原生
System.Drawing.Printing
或常见库如
iTextSharp
(旧版)、
PdfSharp
默认输出的是普通 PDF,连字体嵌入都未必触发——更别说校验 PDF/A 合规性了。 关键点在于:生成 ≠ 合规。你调用
document.Add()
写入文字,若字体未显式嵌入且子集化,或未写入
XMP
元数据块,工具(如 veraPDF)一扫就报
MissingEmbeddedFont
或
InvalidOutputIntent
。 用 iText7 创建 PDF/A-1b 或 PDF/A-2u 的最小必要步骤 iText7 是目前 C# 生态中对 PDF/A 支持最稳的库(注意:必须用
iText7.4.0+
,旧版 iTextSharp 不支持 PDF/A)。它不靠“开关”启用 PDF/A,而靠构造特定
PdfWriter
和
PdfDocument
实例,并全程遵守约束链。 必须使用
PdfWriter
构造时传入
new WriterProperties().SetPdfVersion(PdfVersion.PDF_1_7).SetPdfAConformance(PdfAConformance.PDF_A_1B)
(或
PDF_A_2U
) 文档创建后立即调用
pdfDoc.SetTagged()
(PDF/A-1b 要求逻辑结构标签) 所有字体必须用
PdfFontFactory.CreateFont(..., PdfEncodings.IDENTITY_H, true)
显式加载并设为嵌入(第三个参数
true
) 必须设置输出意图(OutputIntent):用
sRGB IEC61966-2.1
配置项,否则 veraPDF 报
MissingOutputIntent
必须写入 XMP 元数据:调用
pdfDoc.GetCatalog().SetLang("en-US")
+
pdfDoc.GetCatalog().SetViewerPreferences(...)
,再手动注入 XMP 字符串(iText7 不自动补全) 示例关键片段:
PdfWriter writer = new PdfWriter("out.pdf", new WriterProperties().SetPdfVersion(PdfVersion.PDF_1_7) .SetPdfAConformance(PdfAConformance.PDF_A_1B)); PdfDocument pdfDoc = new PdfDocument(writer); pdfDoc.SetTagged(); // 加载字体(必须!) PdfFont font = PdfFontFactory.CreateFont(StandardFonts.HELVETICA, PdfEncodings.IDENTITY_H, true); // 设置 OutputIntent(硬编码路径,不可省) ColorSpace cs = new IccBased(new PdfName("sRGB IEC61966-2.1")); pdfDoc.GetCatalog().Put(new PdfName("OutputIntents"), new PdfArray().Add(new PdfDictionary() .Put(new PdfName("S"), new PdfName("GTS_PDFA1")) .Put(new PdfName("OutputCondition"), new PdfString("sRGB IEC61966-2.1")) .Put(new PdfName("OutputConditionIdentifier"), new PdfString("sRGB IEC61966-2.1")) .Put(new PdfName("Info"), new PdfString("sRGB IEC61966-2.1")) .Put(new PdfName("DestOutputProfile"), new PdfStream(cs.GetProfile()))));
常见失败现象和对应检查点 用 veraPDF 或 PDF/A 验证器扫出失败,别急着改代码——先看错误类型,再定位环节: C知道 CSDN推出的一款AI技术问答工具 下载
MissingEmbeddedFont
:不是“用了系统字体”,而是没在
PdfFontFactory.CreateFont()
中传
true
;或用了
BaseFont.CreateFont()
(iText7 已弃用,会静默失败)
InvalidOutputIntent
:OutputIntent 字典字段名拼错(比如写成
"OutputConditionID"
而非
"OutputConditionIdentifier"
),或 profile 流未正确绑定
MissingXMPMetadata
:没调用
pdfDoc.GetCatalog().SetLang()
,或没手动注入 XMP(iText7 不自动生成,需用
pdfDoc.GetCatalog().Put(new PdfName("Metadata"), metadataStream)
补)
NonEmbeddedFont
:字体文件路径无效(如相对路径在服务端找不到),或字体本身不支持 Unicode 子集(某些 .ttf 有 license 限制) 验证必须用 veraPDF(开源)或 callas pdf Toolbox(商业),Windows 自带的“打印为 PDF”或 Adobe Acrobat “另存为 PDF/A” 按钮生成的文件,常绕过底层校验,不可信。 PDF/A-1b vs PDF/A-2u:选哪个,差别在哪 PDF/A-1b(ISO 19005-1)只保证视觉可再现,不支持透明度、图层、JPEG2000;PDF/A-2u(ISO 19005-2)允许 JPEG2000、OpenType 字体、数字签名,且支持 Unicode 文本搜索(
u
即 Unicode)。但代价是:PDF/A-2u 对字体嵌入要求更严(必须含 Unicode cmap),且部分老旧归档系统只认 PDF/A-1b。 如果目标系统明确要求“PDF/A-1b”,别用
PdfAConformance.PDF_A_2U
—— veraPDF 会直接判失败,不给提示 PDF/A-2u 必须用
PdfEncodings.IDENTITY_H
+ 真实 Unicode 字体(如 Noto Sans CJK),用
StandardFonts.HELVETICA
会因缺少 cmap 报
InvalidUnicodeMapping
两者都不支持
AcroForm
表单字段的交互行为,但 PDF/A-2u 允许表单域存在(只读),PDF/A-1b 连域对象都禁止 归档场景下,除非你确定下游系统支持 PDF/A-2u 且需要 Unicode 搜索,否则优先选 PDF/A-1b——兼容性陷阱少,验证通过率高。 字体嵌入、OutputIntent 字典、XMP 元数据这三处,漏一个,veraPDF 就红标。没有“差不多合规”,只有“全绿才过关”。

相关文章