该页面可以包含自动翻译的文本。
构建文档
当然,你需要使用数据生成 PDF 文档。但很多时候,你还希望使用密码加密 PDF 文件。并且通常还需要向输出文件添加 PDF 元数据。
继续阅读,了解如何指示生成器加密 PDF 文件,以及如何指定文档作者和关键字。
本文是关于用于 PDF 生成的 Layout API 系列文章之一。如果你是该 API 的新用户,请先阅读 Layout API 入门 部分。

Create & Generate
Layout API 的入口点是 PdfDocumentBuilder 类。首先使用 Create 方法创建该类的一个实例。要生成 PDF,请调用该类的 Generate 方法。
Generate 可以将输出保存到文件或流中。该方法的任一版本都需要一个 Action<Document> 类型的委托作为第二个参数。在该委托中,你描述希望得到的文档。库将根据该描述生成 PDF。
加密
要加密输出 PDF,请在 Generate 方法之前调用 Encryption 方法。
你需要创建并提供一个加密处理程序。若要使用密码加密 PDF,请使用 PdfStandardEncryptionHandler 类型的处理程序。
PdfDocumentBuilder.Create()
.Encryption(new PdfStandardEncryptionHandler("owner", "user"))
.Generate("encrypted-with-password.pdf", doc => doc.Pages(_ => { }));
你还可以使用证书加密 PDF。请参阅 加密 PDF 文档 一文。其中包含有关加密处理程序和 PDF 权限的详细信息。
PDF 元数据
在某些工作流中,在输出 PDF 中指定正确的 PDF 关键字和 PDF 作者非常重要。Layout API 为此提供了简便方式。请在 Generate 方法之前调用 Info 方法,并在委托中提供元数据值。
PdfDocumentBuilder.Create()
.Info(info =>
{
info.Author = $"{Environment.UserName}";
info.Title = "Generate encrypted PDF with custom metadata";
info.Keywords = "Metadata keywords encryption";
})
.Generate("metadata.pdf", doc => doc.Pages(_ => { }));
选项
对于相同的内容,库可以创建具有不同内部结构的 PDF 文件。这些选项会影响输出 PDF。
版本
使用 Version 方法设置输出 PDF 的最低 PDF 格式版本。
PdfDocumentBuilder.Create()
.Version(PdfVersion.Pdf17)
.Generate("version.pdf", doc => doc.Pages(_ => { }));
请注意,库可能会创建比指定版本更高版本的 PDF。这发生在文档内容需要更高版本时。换句话说:当文档使用了在指定 PDF 标准版本中不可用的功能时。
对象流
默认情况下,库在生成的 PDF 中使用对象流。这有助于生成更小、压缩更好的文件。
你可以使用 ObjectStreams 方法指示 API 创建不包含对象流的 PDF 文件。
PdfDocumentBuilder.Create()
.ObjectStreams(false)
.Generate("no-object-streams.pdf", doc => doc.Pages(_ => { }));
我建议你继续使用对象流,除非存在某些监管要求。或者当工作流的其他部分无法处理包含对象流的文档时。
流提供程序
库使用流作为中间存储。生成 PDF 时,它会对图像和其他大型对象这样做。库通过流提供程序获取流。当前 PdfDocumentBuilder 实例始终关联一个流提供程序。
库默认使用 PdfMixedStorageStreamProvider。此流提供程序实现提供将数据保留在内存中的流。当数据量过大时,这些流会将其内容刷新到临时文件。这有助于减少内存占用并避免 LOH 碎片化。
在生成 PDF 文件时,你可以使用 IPdfStreamProvider 接口的自定义实现。进行此更改的一个原因可能是磁盘操作缓慢和/或代价高昂。云环境可能符合这一描述。
下面的代码演示如何完全在内存中生成 PDF,而不使用临时文件。请注意,这将比默认选项需要多得多的内存。
using var memoryOnlyProvider = new PdfMemoryStreamProvider();
PdfDocumentBuilder.Create()
.StreamProvider(memoryOnlyProvider)
.Generate("created-without-temp-files.pdf", doc => doc.Pages(_ => { }));
库最终会对通过流提供程序获取的每个流调用 Dispose。你必须自行释放流提供程序实例。