该页面可以包含自动翻译的文本。
将 PDF 转换为 PDF/A
本文介绍如何使用 Docotic.Pdf 将 PDF 文档转换为 PDF/A。这个 .NET 库包含一个高性能的 PDF 到 PDF/A 转换器,可完全离线运行。您还可以使用 Docotic.Pdf 从零开始创建 PDF/A 文档。

为什么将 PDF 转换为 PDF/A?
PDF/A 是为长期归档而设计的 PDF 特殊版本。将标准 PDF 文档转换为 PDF/A 具有以下优势:
-
长期保存
PDF/A 文档可在多年后仍保持可访问和可用,因此非常适合法律、政府和归档用途。 -
符合监管要求
对合规和法律要求严格的行业通常会以 PDF/A 格式存储文档。 -
在不同 PDF 查看器中外观一致
PDF/A 文档在不同系统和不同 PDF 查看器中的显示保持一致。
阅读 什么是 PDF/A? 文章,了解有关 PDF/A 标准的更多信息。
C# 中的 PDF 转 PDF/A
要从 PDF 转换为 PDF/A,您需要:
- 带有 Conformance 附加组件 的 Docotic.Pdf。
- 一个许可证密钥。您可以从 下载页面 获取免费的限时许可证。
以下 C# 代码将 PDF 文件转换为 PDF/A-4:
using var pdf = new PdfDocument("input.pdf");
pdf.SaveAsPdfa("output.pdf", PdfaConformanceLevel.Pdfa4);
SaveAsPdfa 方法由 BitMiracle.Docotic.Pdf.Conformance 命名空间中的附加组件提供。它支持所有 PDF/A 符合性级别:PDF/A-1a、PDF/A-1b、PDF/A-2a、PDF/A-2b、PDF/A-2u、PDF/A-3a、PDF/A-3b、PDF/A-3u、PDF/A-4、PDF/A-4e、PDF/A-4f。输出可以写入文件或流。
如果源文档无法转换为所请求的 PDF/A 符合性级别,SaveAsPdfa 会抛出 ConformanceException。有关详细信息,请参阅 错误处理 部分。
高级转换场景
Docotic.Pdf 支持广泛的 PDF/A 工作流,包括从零创建 PDF/A 文档、将 HTML 转换为 PDF/A,以及将多个文档合并为单个 PDF/A 文件。
创建 PDF/A 文档
Docotic.Pdf 提供了多种在 .NET 中创建 PDF 文档 的方式。您可以使用相同的 SaveAsPdfa 方法,结合 Core API 或 Layout API 生成 PDF/A 文档。
以下 C# 代码使用 Core API 创建一个 PDF/A-3u 文档:
using var pdf = new PdfDocument();
pdf.Pages[0].Canvas.DrawString("Hello PDF/A");
pdf.SaveAsPdfa("output.pdf", PdfaConformanceLevel.Pdfa3U);
使用 Layout API,您先生成常规 PDF 文档,然后将其转换为 PDF/A。此代码示例展示如何生成 PDF/A-1b 文档:
using var ms = new MemoryStream();
PdfDocumentBuilder.Create().Generate(ms, doc => doc.Pages(pages =>
{
pages.Content().Text("Hello, world!");
}));
using var pdf = new PdfDocument(ms);
pdf.SaveAsPdfa("output.pdf", PdfaConformanceLevel.Pdfa1B);
HTML 转 PDF/A
HtmlToPdf 附加组件可将 HTML 转换为 PDF。要为归档准备结果,请将生成的 PDF 保存为 PDF/A:
var uri = new Uri("https://google.com");
var options = new HtmlConversionOptions
{
PreserveStructureInformation = true,
};
using var converter = await HtmlConverter.CreateAsync();
using var pdf = await converter.CreatePdfAsync(uri, options);
pdf.SaveAsPdfa("output.pdf", PdfaConformanceLevel.Pdfa3A);
PreserveStructureInformation = true 选项有助于生成可访问文档。这对于 PDF/A-1a、PDF/A-2a 或 PDF/A-3a 符合性级别很重要。
将 PDF 文档合并为 PDF/A
Docotic.Pdf 支持 合并 PDF 文档。将 PdfDocument.Save 调用替换为 SaveAsPdfa,即可将合并后的文档保存为 PDF/A:
using var pdf = new PdfDocument("first.pdf");
pdf.Append("second.pdf");
pdf.SaveAsPdfa("merged.pdf", PdfaConformanceLevel.Pdfa1B);
您可以在其他 PDF 编辑 场景中应用相同原理。例如,删除 PDF 页面、编辑文本、展平表单字段,最后保存为 PDF/A。
在 C# 中创建 ZUGFeRD / Factur-X 文件
Factur-X / ZUGFeRD 是一种基于 PDF/A-3 的欧洲电子发票标准。您可以使用 Docotic.Pdf 嵌入 XML 发票文件,并生成有效的 Factur-X / ZUGFeRD 文档:
using var pdf = new PdfDocument();
PdfFileSpecification xml = pdf.CreateFileAttachment("your_path_to/xrechnung.xml");
xml.Relationship = "Alternative";
pdf.SharedAttachments.Add(xml);
var fx = new XmpSchema("fx", "urn:factur-x:pdfa:CrossIndustryDocument:invoice:1p0#");
var props = fx.Properties;
props.Add(new XmpProperty("DocumentType", new XmpString("INVOICE")));
props.Add(new XmpProperty("DocumentFileName", new XmpString("xrechnung.xml")));
props.Add(new XmpProperty("Version", new XmpString("3.0")));
props.Add(new XmpProperty("ConformanceLevel", new XmpString("XRECHNUNG")));
pdf.Metadata.Schemas.Add(fx);
pdf.SaveAsPdfa("zugferd.pdf", PdfaConformanceLevel.Pdfa3A);
创建 Order-X 文档
Order-X 是另一种 EU 标准,用于电子处理采购订单。以下 C# 代码片段展示如何使用 COMFORT 配置文件创建 Order-X 文档:
using var pdf = new PdfDocument();
using (var file = File.OpenRead("order-data-comfort.xml"))
{
PdfFileSpecification xml = pdf.CreateFileAttachment(file, "order-x.xml");
xml.Relationship = "Data";
pdf.SharedAttachments.Add(xml);
}
var fx = new XmpSchema("fx", "urn:factur-x:pdfa:CrossIndustryDocument:1p0#");
var props = fx.Properties;
props.Add(new XmpProperty("DocumentType", new XmpString("ORDER")));
props.Add(new XmpProperty("DocumentFileName", new XmpString("order-x.xml")));
props.Add(new XmpProperty("Version", new XmpString("1.0")));
props.Add(new XmpProperty("ConformanceLevel", new XmpString("COMFORT")));
pdf.Metadata.Schemas.Add(fx);
pdf.SaveAsPdfa("order-x.pdf", PdfaConformanceLevel.Pdfa3B);
将受保护的 PDF 文件转换为 PDF/A
转换加密 PDF 文件并没有什么不同。使用正确的密码打开文档,然后调用 SaveAsPdfa:
using var pdf = new PdfDocument(fileName, new PdfStandardDecryptionHandler("password"));
pdf.SaveAsPdfa("result.pdf", PdfaConformanceLevel.Pdfa4E);
批处理
您可以自动将多个 PDF 文件转换为 PDF/A。枚举目录中的所有 PDF 文件,并将每个文档转换为 PDF/A。以下代码示例展示如何并行转换文件:
public static async Task ConvertAsync(string directoryPath)
{
string[] files = Directory.GetFiles(directoryPath, "*.pdf", SearchOption.AllDirectories);
if (files.Length == 0)
return;
var semaphore = new SemaphoreSlim(Environment.ProcessorCount);
var tasks = new List<Task>(files.Length);
foreach (var f in files)
{
await semaphore.WaitAsync();
var task = Task.Run(() =>
{
string outputFileName = $"{Path.GetFileName(f)}-{Guid.NewGuid()}.pdf";
try
{
using var pdf = new PdfDocument(f);
pdf.SaveAsPdfa(outputFileName, PdfaConformanceLevel.Pdfa1B);
}
finally
{
semaphore.Release();
}
});
tasks.Add(task);
}
await Task.WhenAll(tasks);
}
当您为任意 PDF 文件实现转换工作流时,最好验证所有生成文件是否符合 PDF/A。您可以在 评估转换质量 部分找到可直接使用的批量转换和验证应用程序。
错误处理
转换在某些情况下可能失败。例如,当:
- 输入文件不是 PDF
- 为加密 PDF 提供了无效密码
- 无法为 PDF/A 嵌入字体字节
在这些情况下,Docotic.Pdf 会抛出异常。以下示例代码展示如何处理异常:
try
{
using var pdf = new PdfDocument("input.pdf");
pdf.SaveAsPdfa("output.pdf", PdfaConformanceLevel.Pdfa1B);
}
catch (PdfException ex)
{
Console.WriteLine($"Problem with an input document: {ex.Message}");
}
catch (ConformanceException ex)
{
Console.WriteLine($"Unable to convert to PDF/A: {ex.Message}");
}
从 PDF/A 转换为 PDF
将 PDF/A 转换为 PDF 有时用于更方便地编辑文档。该过程比 PDF 转 PDF/A 简单得多。您只需删除一部分 XMP 元数据。示例代码:
using var pdf = new PdfDocument("pdfa-compliant.pdf");
var schemas = pdf.Metadata.Schemas;
for (int i = 0; i < schemas.Count; ++i)
{
if (schemas[i].Namespace == "http://www.aiim.org/pdfa/ns/id/")
{
schemas.RemoveAt(i);
--i;
}
}
pdf.Save("regular.pdf");
为什么选择 Docotic.Pdf 进行 PDF 到 PDF/A 转换?
Docotic.Pdf 是一个高性能、纯 C# .NET 库,没有外部依赖。您可以使用它在 Windows、Linux、macOS、Android、iOS 或云环境中生成 PDF/A 文档。此外,Docotic.Pdf 还提供以下优势:
独立离线转换
转换完全在您的计算机上进行。不会向外部服务器或第三方提供商传输任何数据。离线转换有助于保护敏感文档,因为数据不会离开您的环境。
质量
Docotic.Pdf 的设计目标是在转换过程中尽可能保留原始信息,同时不牺牲质量。
ISO 合规性
Docotic.Pdf 生成符合以下 ISO 标准的 PDF/A 文件:
- ISO 19005-1:2005 (PDF/A-1)
- ISO 19005-2:2011 (PDF/A-2)
- ISO 19005-3:2012 (PDF/A-3)
- ISO 19005-4:2020 (PDF/A-4)
每个 Docotic.Pdf 构建版本都要通过数千个自动化测试。PDF 转 PDF/A 测试使用来自不同来源的大量 PDF 文件,并将它们转换为各种 PDF/A 符合性级别。随后会验证生成文件是否符合 PDF/A。
一组测试检查 veraPDF 是否对转换后的文件报告问题。另一组测试 将每个生成文件进行比较,与其预期的 PDF/A 版本对比;该版本已由 veraPDF 和 Adobe Acrobat Preflight 验证不存在合规问题。
评估转换质量
我们提供开源的 PdfToPdfa 项目。它是一个将 PDF 文件转换为 PDF/A 的 .NET 控制台应用程序。转换后,应用会验证每个生成的文档。该项目使用 Docotic.Pdf 进行转换,并使用 veraPDF 进行验证。
您可以在命令行模式下使用此应用,以自动化您的 PDF/A 工作流。也可以在 UI 模式下快速评估转换质量和性能。

该应用可以处理任意 PDF 文件或目录。为了方便您,项目仓库还包含来自 veraPDF corpus 和 Isartor Test Suite 的测试文件。
转换为 PDF/A 时会发生什么?
PDF/A 规范定义了大量符合文档要求的条件。转换器会验证并强制执行这些要求,以生成有效的 PDF/A 文件。从高层来看,它会检查每个 PDF 对象,并修复检测到的 PDF/A 合规问题。
并非所有 PDF 都能在不改变内容的情况下转换为 PDF/A。某些 PDF 功能被所选 PDF/A 符合性级别禁止,因此转换器必须移除或转换这些功能。因此,转换可能是有损过程。
例如,PDF/A-1 不允许可选内容(图层)、嵌入文件(附件)或透明度。如果原始 PDF 文档使用了这些功能,转换器会展平图层、移除附件和透明度。如果保留这些内容很重要,请选择支持它们的 PDF/A 符合性级别:
- 所有 PDF/A-2、PDF/A-3 和 PDF/A-4 符合性级别都支持透明度和可选内容。
- PDF/A-3、PDF/A-4 和 PDF/A-4f 支持任意嵌入文件。PDF/A-2 和 PDF/A-4 仅支持嵌入的 PDF/A 文件。
让我们看看 Docotic.Pdf 如何修复最常见的问题。
字体和文本
转换器会尝试嵌入文档中使用的每一种字体。对于尚未嵌入的字体,它会先尝试从系统字体集合或自定义字体源加载合适的字体数据。如果找不到匹配字体,则使用替代字体。
您可以通过提供自定义字体加载器来定制此过程。IFontLoader 接口用于加载字体数据。例如,DirectoryFontLoader 实现会从一个或多个指定目录加载字体字节。
当 IFontLoader 无法加载请求的字体时,您还可以提供 IFallbackFontProvider 接口的实现来提供替代字体。
以下示例展示如何定制字体加载:
public static void ConfigurePdfToPdfa(
string fileName,
PdfaConformanceLevel level,
Stream output,
IFontLoader? fontLoader,
IFallbackFontProvider? fallbackFontProvider)
{
var config = PdfConfigurationOptions.Create();
if (fontLoader != null)
config.FontLoader = fontLoader;
if (fallbackFontProvider != null)
config.FallbackFontProvider = fallbackFontProvider;
using var pdf = new PdfDocument(fileName, config);
pdf.SaveAsPdfa(output, level);
}
Docotic.Pdf 还会修复不一致的字形宽度、CMap 和 ToUnicode 流。转换过程中会移除未定义字符。
元数据
转换器会修正或移除无效的元数据架构或属性,添加 pdfaid 架构,并同步 XMP 元数据与文档信息字典。
Conformance 附加组件还为 PdfDocument 提供 ReadPdfaConformance 扩展方法。使用此方法可读取 XMP 元数据中声明的 PDF/A 符合性级别:
using var pdf = new PdfDocument("input.pdf");
PdfaConformanceLevel? level = pdf.ReadPdfaConformance();
颜色
转换器会为设备颜色提供输出意图 ICC 配置文件,因为 PDF/A 文档不允许使用依赖设备的颜色。它还会修复不符合规范的输出意图和色彩空间。
生成 PDF/A-1 文档时会移除透明度。这会影响混合模式、软遮罩和透明度组。无效的图像属性也会被修复。
嵌入文件
嵌入文件的处理取决于 PDF/A 符合性级别。在 PDF/A-1 中,所有嵌入文件都会被移除。
在 PDF/A-2 和 PDF/A-4 中,嵌入的 PDF 文件会转换为 PDF/A。非 PDF 附件会被移除。对于嵌入的 PDF/A 文件,PDF/A-4 还会修复 MIME 类型和文件关系。
在 PDF/A-3 中,附件不会被移除,但会修复文件关系和 MIME 类型。
交互功能
转换器会生成缺失或无效的外观流。它还会修复无效的注释属性,展平不允许类型的注释,并移除不允许类型的动作。
PDF/A-2、PDF/A-3 和 PDF/A-4 会移除 XFA 表单。只有 PDF/A-1 允许 XFA 表单,但长期归档仍不推荐使用。
在目标为 PDF/A-1 时,会展平可选内容。对于其他符合性级别,转换器会修复可选内容配置字典中不完整的顺序数组、缺失名称或重复名称。
数字签名
数字签名 从设计上不允许修改已签名内容。如果 PDF 的已签名部分存在 PDF/A 合规问题,转换器会修复这些问题并使签名失效。
其他方面
为便于访问,若文档缺少基本结构信息,转换器会添加该信息。它还会修复无效或非标准的结构标签。这适用于 PDF/A-1a、PDF/A-2a 和 PDF/A-3a 文档。
PDF/A 文件不得加密,因此转换器不允许对输出文件进行加密。
PDF/A 不允许 LZW 压缩数据。转换器会使用 Flate 压缩重新压缩 LZW 流。它还会修复不符合规范的数组、字典、数字、名称和字符串对象。
无效的文件头或交叉引用部分也会自动修复。
结论
带有 Conformance 附加组件的 Docotic.Pdf 提供了高质量的 PDF 到 PDF/A 转换器。您可以将现有 PDF 文档转换为任意 PDF/A 符合性级别,也可以从零创建 PDF/A 文档。该库完全在本地运行,因此您的数据不会离开服务器。
您可以在示例仓库的 PDF/A 部分 中查看用于创建和处理 PDF/A 文档的可运行 C# 和 VB.NET 示例。
此外,还有用于 PDF 到 PDF/A 转换的开源 PdfToPdfa 应用程序。您可以使用它来自动化 PDF/A 工作流,或者 պարզապես 将 PDF 文件转换为 PDF/A。
常见问题
如何选择合适的 PDF 到 PDF/A 转换器?
优秀的 PDF 到 PDF/A 转换器应当:
- 生成符合 PDF/A 的文件。
- 保留源文档中的信息和视觉外观。
- 在本地运行,不向第三方服务器发送文件。
- 运行速度快。
- (如果需要自动化)支持无界面执行。
Docotic.Pdf 库满足所有这些条件,是从 PDF 转换为 PDF/A 的良好选择。
如何验证 PDF/A 文档符合规范?
使用验证软件。优秀的 PDF/A 验证器应当:
- 深入遵循 PDF/A 的 ISO 标准。
- 在本地运行,不向第三方服务器发送文件。
- 运行速度快。
- (如果需要自动化)支持无界面执行。
veraPDF 是符合这些要求的行业标准验证工具。
如何自动化 PDF 到 PDF/A 的转换工作流?
使用 Docotic.Pdf Conformance 附加组件转换 PDF 文件。使用 veraPDF 验证器验证结果。跟踪转换和验证进度。
开源的 PdfToPdfa 应用程序 实现了这一工作流。您可以将其作为自定义实现的起点。
应该使用哪个 PDF/A 版本?
请阅读 如何选择 PDF/A 版本 部分。
我可以将 XML 文件嵌入 PDF 以用于 ZUGFeRD 吗?
可以,当然可以。请查看 生成 ZUGFeRD / Factur-X 文件 部分中的示例。
如何保护 PDF/A 文档?
从技术上讲,这是不可能的。PDF/A 文件不得加密。