该页面可以包含自动翻译的文本。

在 C# 中编辑 PDF

使用 Docotic.Pdf 修改您的 PDF 文档。它是 C# 和 VB.NET 的 PDF 编辑库,结合了强大的功能和直观的 API。

Docotic.Pdf 库 9.5.17573-dev 回归测试 14,726 通过 NuGet 总下载量 4,765,230
PDF 编辑器图标

Docotic.Pdf 提供了很多编辑 PDF 文档的方法。以下是该库用于 PDF 编辑的一些主要功能:

  • 将多个 PDF 合并为一个或将单个 PDF 拆分为多个文件。
  • 减小 PDF 文件大小。
  • 重新排列、删除、旋转或提取页面。
  • 读取、更改或删除 PDF 元数据。
  • 使用数字签名对 PDF 进行签名。
  • 加密文档或从 ​​PDF 中删除密码。
  • 添加、编辑或删除注释和附件。
  • 填写 AcroForms,添加或删除表单控件。
  • 展平表单字段和注释以使其成为 PDF 内容的一部分。
  • 在 PDF 中添加、删除或替换文本。
  • 插入、替换和调整图像大小。
  • 添加水印和背景。
  • 将扫描的文档转换为可编辑和可搜索的文本。

在接下来的部分中,我将更详细地描述 PDF 编辑功能。这些部分还包含代码片段和相关资源的链接。

合并和拆分 PDF

本节介绍两个具有相反目标的功能。

在 C# 和 VB.NET 中拆分和合并 PDF

合并 PDF

合并 PDF 文件时,您将创建一个 PDF 文档。合并的 PDF 通常包含来自多个现有 PDF 文件的相关信息。

这是一个代码片段,展示了如何使用 Docotic.Pdf 合并 PDF 文件。

using var pdf = new PdfDocument("first.pdf");
pdf.Append("second.pdf");
pdf.Save("merged.pdf");

代码非常简单,因为它展示了最基本的情况。我们有一篇文章描述了更复杂的合并情况。例如,它展示了如何合并加密文档。

拆分PDF

拆分是指从原始 PDF 中提取选定的页面以创建一个或多个新的 PDF 文件。当您只想共享文档的一部分时,此过程非常有用。

以下代码片段显示如何从 PDF 的每一页创建新文档。

using var pdf = new PdfDocument("compound.pdf");
for (int i = 0; i < pdf.PageCount; ++i)
{
    using PdfDocument copy = pdf.CopyPages(i, 1);

    // 当复制的页面引用未使用的资源(例如字体、图像、图案)时有助于减少文件大小。
    copy.RemoveUnusedResources();
    copy.Save(i + ".pdf");
}

在专门的文章中了解实现 PDF 分割器的其他方法。

PDF 压缩

压缩 PDF 时主要有两种方法。第一种方法是只应用不改变文件内容的操作,只改变其形式。第二种方法还包括可能导致细节或文档质量损失的更改,以实现更好的压缩。

无损 PDF 压缩

默认情况下,该库会保存 PDF 对象,以便它们占用更少的字节。为此,它会排除未使用的对象、写入未格式化的对象,并尽可能使用较短的格式。

为了进一步提高压缩率,Docotic.Pdf 还在输出 PDF 中生成对象流。这是以最紧凑的表示形式写入对象的另一种形式。对象流使用 Flate 算法进行压缩。

您可以使用 保存选项 来影响库保存对象的方式。

某些文档包含重复的字体、图像、颜色配置文件和其他对象。增量更新的文档和通过合并多个文档创建的文件通常会出现这种情况。使用 PdfDocument.ReplaceDuplicateObjects 方法对这些对象进行重复数据删除可以大幅减少输出大小。

文档的页面可以引用未使用的资源。例如,以前在页面上可见但现在不再可见的图像。使用 PdfDocument.RemoveUnusedResources 方法可删除此类资源。

PDF 上的所有这些操作都可以减小文件大小而不会损失质量。

有损变换

对于包含图像的文件,缩小 PDF 大小的最有效方法之一是 更改图像的压缩方案。例如,对图像使用 JPEG 等有损压缩将减小尺寸。但其副作用是,图像上会出现压缩伪影和细节损失。

如果 PDF 中的图像比需要的大,您可以 调整其大小。这可以提供更好的压缩效果。另一个选项是将图像转换为黑白(双色调)。

您可以扁平化表单字段和注释以节省一些空间。当您的文档中不再需要可编辑的注释和表单字段时,这样做很有意义。

字体会占用文档中的大量空间。PdfDocument.RemoveUnusedFontGlyphs 方法可以从字体中删除未使用的字形以优化输出大小。字体子集是此过程的另一个名称。您甚至可以从文档中完全删除字体字节(取消嵌入字体)。当文档包含流行字体(如 Arial)的字节时,这可能很有意义。

其他转换会直接从文档中删除信息。您可以删除元数据、结构信息和私有应用程序数据。这些数据不可见,但仅当它们对文档用户不重要时才删除。

要了解更多详细信息并查看一些代码示例,请阅读有关如何减小 PDF 文件大小的文章。

重新排序 PDF 中的页面

更改 PDF 中页面顺序的理由有很多。例如,您可能需要将相关信息分组在一起,或者通过确保文档的逻辑性来提高文档的可读性。

重新排列 PDF 中的页面

除了 合并和拆分页面 功能外,Docotic.Pdf 还提供了一系列其他方法来重新排列 PDF 中的页面。我将使用 C# 代码片段和 Docotic.Pdf API 来展示如何组织 PDF 页面。

您可以在示例代码的 页面和导航 组中找到本节示例的完整测试项目。我在代码片段中使用了 ten-pages.pdf。这是一个简单的测试文档,每页都有一个Page N标题。

移动 PDF 页面

以下代码片段显示了如何移动连续的页面范围。代码将页面的前半部分移动到文档末尾。

using var pdf = new PdfDocument("ten-pages.pdf");

pdf.MovePages(0, 5, pdf.PageCount);

pdf.Save("continuous-move.pdf");

可以移动任意页面集。以下代码将奇数页移动到文档末尾。

using var pdf = new PdfDocument("ten-pages.pdf");

int[] indexes = [0, 2, 4, 6, 8];
pdf.MovePages(indexes, pdf.PageCount);

pdf.Save("arbitrary-move.pdf");

要仅移动一页,请使用PdfDocument.MovePage方法。

交换 PDF 页面

要交换两个页面,请使用如下代码片段。

using var pdf = new PdfDocument("ten-pages.pdf");

pdf.SwapPages(9, 0);
pdf.SwapPages(8, 1);

pdf.Save("swapped.pdf");

PdfDocument.SwapPages 方法接受应相互取代的两个页面的索引。当页面数不等于 2 时,请使用 移动页面 方法之一。

添加和插入页面

任何 PdfDocument 都至少包含一页。当您创建新文档时,库会隐式添加一页。

以下是如何使用 Docotic.Pdf API 在 PDF 中插入空白页。您可以在索引从0PageCount的位置插入页面(含)。

using var pdf = new PdfDocument();

var newPage = pdf.InsertPage(0);
newPage.Canvas.DrawString("This is the new first page");

pdf.Save("two-pages.pdf");

要向 PDF 添加空白页,请使用 PdfDocument.AddPage 方法。该方法将新页面添加到文档末尾。它的作用与 pdf.InsertPage(pdf.PageCount) 调用相同。

要添加或插入其他文档的页面,请使用 附加 PDF 部分中所述的组合调用。您可以使用组合调用为 PDF 添加封面页。

重复的 PDF 页面

使用库 API,您可以将复制操作作为两个连续的操作执行。第一个是复制页面操作。请参阅 拆分 PDF 部分中的代码示例。

第二个是粘贴页面操作。对于此操作,使用 PdfDocument.Append 方法。然后 移动附加的页面 到所需的位置。

提取页面

以下代码片段展示了如何从 PDF 中提取页面。它从源文档中提取前三页。

using var pdf = new PdfDocument("ten-pages.pdf");

using (var extracted = pdf.ExtractPages(0, 3))
{
    extracted.RemoveUnusedResources();
    extracted.Save("three-pages.pdf");
}

pdf.Save("seven-pages.pdf");

ExtractPages 方法会从文档中删除页面。因此,源文档中只剩下七页。该库不允许从仅包含一页的文档中提取页面。

我们建议从提取的页面文档中删除未使用的资源。

从 PDF 中删除页面

查看演示如何删除 PDF 文档中的页面的代码片段。它实际上使用 RemovePage 方法的不同重载删除了两个页面。第一个重载接受页面索引作为其参数。第二个重载接受页面对象。

using var pdf = new PdfDocument("ten-pages.pdf");
pdf.RemovePage(0);
pdf.RemovePage(pdf.Pages[0]);
pdf.Save("without-first-two-pages.pdf");

要一次删除多个页面,请使用 PdfDocument.RemovePages 方法。该方法可重载页面索引或页面对象数组。

数字签名

Docotic.Pdf 实现了许多 PDF 数字签名操作,可以帮助您维护 PDF 文档的可信度和法律有效性。以下是该库可以执行的一些示例:

使用证书签署 PDF。在 PDF 中添加数字签名是确认签名者身份并确保签名后无人更改文档的方法。

认证签名。要对 PDF 添加其他限制,您可以使用认证签名对其进行签名。签名后,您可以完全锁定 PDF 或允许几种类型的更改。

验证 PDF 中的签名。检查数字签名的有效性,以确认文档的签名部分没有更改。

允许多个签名。合同、协议和表格通常需要多方签署一份文件。向 PDF 添加多个签名需要 逐步保存 文件。

嵌入签名时间戳。可以在签名选项中指定时间戳颁发机构 URL 及其凭据(可选)。该库将在签名中嵌入收到的时间戳。

嵌入证书。该库自动将签名证书嵌入数字签名中。

数字签名页面包含示例代码和有关每个操作的更多信息。

保护 PDF

您可以使用三种功能来确保 PDF 安全。Docotic.Pdf 可以双向使用它们:该库可以保护 PDF 并解锁受保护的 PDF。

PDF 安全性

密码保护

此功能允许您设置密码以限制对 PDF 的访问。根据密码类型,PDF 将需要正确的密码才能打开或修改文档。

PDF 中有两种类型的密码:

  • 打开密码(用户密码)。打开和查看 PDF 需要这种类型的密码。如果没有正确的密码,符合要求的 PDF 查看器将无法打开文档。
  • 权限密码(所有者密码)。删除 PDF 权限需要此密码。使用所有者密码打开 PDF 允许执行所有操作,即使权限限制某些操作,例如打印、复制或编辑 PDF。

您可以为同一个 PDF 文档 设置两个密码。阅读 解密 PDF 文件 以了解如何从 PDF 文档中删除密码。

加密

PDF 加密和 PDF 密码协同工作,确保 PDF 中的敏感信息仅供合法用户使用。只有拥有正确解密密钥或密码的用户才能查看内容。

Docotic.Pdf 可以使用 RC4 40 位、RC4 128 位、AES 128 位和 AES 256 位加密 算法加密 PDF 文件。

权限和限制

您可以在 PDF 上 设置各种权限,例如限制打印、复制文本、编辑文档等。这些权限仅影响使用用户密码打开 PDF 时的体验。对于使用所有者密码打开 PDF 的用户,任何限制均不适用。

要从 PDF 中删除权限,您需要先删除 PDF 安全密码。阅读有关如何使用 C# 和 Docotic.Pdf API 执行此操作 的信息。

要了解如何确保 PDF 完整性 以及 PDF 安全性,请阅读有关数字签名的部分。

PDF 中的元数据

PDF 元数据是嵌入在 PDF 文件中的信息,提供有关文档的详细信息。元数据主要有两个来源:PDF 文档属性和 XMP 元数据。

文档属性也通常被称为文档信息字典、文件信息、元数据字段、文档属性和文件属性。

XMP(可扩展元数据平台)元数据基本上是嵌入在 PDF 中的 XML 文件。XMP 使用灵活的数据模型,可以存储任何一组元数据属性。此元数据使用命名空间对相关属性进行分组。一些常见的命名空间包括 XMP Core/XMP Basic 和 Dublin Core。

Docotic.Pdf 完全支持 XMP 元数据和文档属性。请注意,PDF 2.0 标准将大多数文档信息字典属性标记为已弃用。唯一的例外是创建日期和修改日期。

您可以在示例代码的元数据组中找到本节示例的完整测试项目。

文档属性

了解如何使用 Docotic.Pdf 编辑文档属性。

using var pdf = new PdfDocument("file.pdf");
pdf.Info.Author = "An example code";
pdf.Info.Subject = "Showing how to access and change document metadata";
pdf.Info.Title = "Custom title goes here";
pdf.Info.Keywords = "pdf Docotic.Pdf";

pdf.Save("updated-file.pdf");

您可以更改每个属性的值,但请注意,默认情况下,库会在保存 PDF 之前自动更新某些属性。您可以在 保存选项 中更改此设置。

要删除文档属性中指定的所有元数据,请使用 PdfInfo.Clear 方法。如果您愿意,该方法只能删除自定义属性。

XMP 元数据

此代码片段显示如何更改 PDF 文档中 XMP 元数据的属性。

using var pdf = new PdfDocument("file.pdf");

pdf.Metadata.DublinCore.Creators = new XmpArray(XmpArrayType.Ordered);
pdf.Metadata.DublinCore.Creators.Values.Add(new XmpString("me"));
pdf.Metadata.DublinCore.Creators.Values.Add(new XmpString("Docotic.Pdf"));
pdf.Metadata.DublinCore.Format = new XmpString("application/pdf");

pdf.Metadata.Pdf.Producer = new XmpString("me too!");

pdf.Save("updated-file.pdf");

代码更改了 Dublin Core 和 Adob​​e PDF 架构中的属性。请注意,Producer 属性会因 默认保存选项 而被覆盖。

您可以使用XmpMetatada.Save方法之一提取原始 XMP 元数据。该方法将生成具有所有属性的 XML。

要从文档中删除所有 XMP 元数据,请使用XmpMetadata.Unembed方法。

同步元数据

最好确保 XMP 元数据和文档信息属性的相应属性具有相同的值。如果您在同一文件中编辑两个元数据源,则尤其如此。

使用 PdfDocument.SyncMetadata 方法同步 XMP 元数据和文档信息中的值。当两个源中的属性都发生更改时,该方法将使用一个源中的值覆盖另一个源。阅读 该方法的文档 了解更多详细信息。

PDF 书签

PDF 文档可以包含特殊的快捷方式或链接,帮助读者快速导航到特定的部分或页面。PDF 大纲是书签的另一个名称。

PDF 大纲

查看器应用通常显示书签,就像书中的目录一样,但具有交互性。当读者点击书签时,查看器应用会跳转到文档的指定部分。使用 链接注释 可以实现类似的行为。

以下是一个 C# 代码片段,展示了如何向 PDF 添加书签:

using var pdf = new PdfDocument("ten-pages.pdf");

var root = pdf.OutlineRoot;
root.AddChild("Fifth page", 4);
root.AddChild("Seventh page", pdf.Pages[6]);

pdf.PageMode = PdfPageMode.UseOutlines;
pdf.Save("simple-bookmarks.pdf");

PDF 大纲可以有主书签和子书签,使构建大型文档变得更加容易。以下是在 PDF 中创建子书签的方法:

using var pdf = new PdfDocument("ten-pages.pdf");

var root = pdf.OutlineRoot;
var evenPages = root.AddChild("Even pages");

evenPages.AddChild("Second page", 1);
evenPages.AddChild("Fourth page", 3);

pdf.PageMode = PdfPageMode.UseOutlines;
pdf.Save("even-pages-bookmarks.pdf");

您可以为书签项目应用字体和颜色。查看创建 带样式的大纲 的完整示例。

要从 PDF 中删除书签,请使用 RemoveChildRemoveChildAt 方法。您可以通过在根节点上调用 RemoveAllChildren 方法来删​​除所有书签。

文件附件

PDF 附件是嵌入在 PDF 文档中的外部文件。人们通常也将这些文件称为嵌入文件和文件附件。您可以附加任何文件:图像、音频/视频文件、其他 PDF、Word 文档、Excel 电子表格或其他任何内容。

如果您想将 PDF 附加在一起,创建合并的 PDF 文件,请查看有关合并 PDF 文档的文章。

以下是 C# 代码,展示了如何在 Docotic.Pdf API 的帮助下将附件添加到 PDF。

using var pdf = new PdfDocument();

var excelFile = pdf.CreateFileAttachment("this-year-figures.xlsx");
pdf.SharedAttachments.Add(excelFile);

pdf.Save("shared-attachment.pdf");

上述代码将文件添加为共享附件。读者可以在其查看器的附件面板中找到附加的文件。

还可以向 PDF 页面添加附件。此类附件与任何 其他注释 一样在页面内容中可见。

using var pdf = new PdfDocument();

var page = pdf.Pages[0];
page.Canvas.DrawString(20, 100, "Here is this year's figures document:");

var bounds = PdfRectangle.FromLTRB(155, 100, 165, 110);
var excelFile = pdf.CreateFileAttachment("this-year-figures.xlsx");
pdf.Pages[0].AddFileAnnotation(bounds, excelFile);

pdf.Save("page-attachment.pdf");

查看示例代码的附件组,找到本节示例的完整测试项目。

要从 PDF 中删除附件,您需要枚举共享附件和页面注释,并删除不需要的项目。请参阅下面的枚举代码示例。要删除所有共享注释,您可以使用 pdf.SharedAttachments.Clear() 调用。

您还需要枚举集合以从 PDF 中提取嵌入文件。以下是示例代码:

using var pdf = new PdfDocument("file-with-attachments.pdf");

int i = 0;
foreach (var attachment in pdf.SharedAttachments)
{
    if (attachment?.Contents == null)
        continue;

    var fileName = attachment.Specification ?? $"attachment{i++}";
    attachment.Contents.Save(fileName);
}

foreach (var widget in pdf.GetWidgets())
{
    var attachment = (widget as PdfFileAttachmentAnnotation)?.File;
    if (attachment?.Contents == null)
        continue;

    var fileName = attachment.Specification ?? $"attachment{i++}";
    attachment.Contents.Save(fileName);
}

页面标签

PDF 页面标签是分配给 PDF 文档中页面的自定义名称或数字。与标准页码不同,页面标签可以包含字母、数字甚至罗马数字的混合。页面标签的其他名称是页面标识符和页面名称。

以下是使用 Docotic.Pdf 向 PDF 添加页面标签的方法:

using var pdf = new PdfDocument("ten-pages.pdf");

pdf.PageLabels.AddRange(0, 3, PdfPageNumberingStyle.LowercaseRoman);
pdf.PageLabels.AddRange(4, PdfPageNumberingStyle.DecimalArabic, string.Empty, 5);
pdf.PageLabels.AddRange(7, PdfPageNumberingStyle.DecimalArabic, "Appendix page ", 1);

pdf.Save("page-labels.pdf");

前四页将带有标签 iiiiiiiv。接下来的三个标签是 567。对于剩余的页面,标签将为 Appendix page 1Appendix page 2Appendix page 3

OCR PDF

某些 PDF 文档包含扫描页面,需要先进行光学字符识别 (OCR),然后才能从中提取文本。OCR 的另一个用例是从使用自定义字形到 Unicode 映射的 PDF 中提取文本。

使用 OCR 扫描 PDF 来提取文本

我们有一篇博客文章展示了如何 OCR 扫描文档。该文章包含一个不可搜索的 PDF 示例,并展示了如何使用 Tesseract OCR、C# 代码和 Docotic.Pdf 识别纯图像 PDF 中的文本。您还可以借助 Docotic.Pdf 向扫描的 PDF 文件添加 OCR 文本层。

编辑页面

本节讨论对现有 PDF 页面的更改,例如:

  • 如何旋转 PDF 页面
  • 如何更改页面大小
  • 在页面画布上使用矢量图形
  • 添加 HTML 内容

阅读该库的布局 API,了解如何从页眉和页脚、表格、图像、文本段落等构建块创建 PDF 文档

查看其他部分以获取有关以下方面的信息:

旋转页面

请参阅 C# 代码片段以了解如何仅旋转 PDF 中的一页:

using var pdf = new PdfDocument("existing.pdf");

pdf.Pages[0].Rotation = PdfRotation.Rotate180;

pdf.Save("rotated.pdf");

代码将第一页旋转 180 度。您也可以将 PDF 页面旋转 0 度、90 度和 270 度。

更改页面大小

Docotic.Pdf 提供了多种方法来更改 PDF 的页面大小。在最简单的情况下,您可以使用 PdfPage 对象的 WidthHeight 属性来指定所需的大小。对于现有文档,它不会调整文档页面内容的大小。并且它不会删除任何内容。它只会隐藏指定大小矩形之外的所有内容。

类似的方法是裁剪页面。你可以使用 C# 代码更改页面的CropBox,如下所示:

using var pdf = new PdfDocument("existing.pdf");

var page = pdf.Pages[0];
var cropBoxBefore = page.CropBox;
page.CropBox = new PdfBox(0, cropBoxBefore.Height - 256, 256, cropBoxBefore.Height);

pdf.Save("cropped.pdf");

如果您想将页面的一部分保存为图像,更改裁剪框是正确的方法。

如果目标是让所有内容在不同大小的页面上都可见,则使用缩放方法。在下面的代码片段中,我从页面创建了一个 XObject。XObject 就像一个矢量图像。您可以在多个页面上绘制相同的对象,并根据需要缩放和旋转它。

XObject 准备好后,我清除之前的页面内容,调整页面大小,然后在调整大小的页面上绘制对象。

using var pdf = new PdfDocument("existing.pdf");

var page = pdf.Pages[0];
var pageXObject = pdf.CreateXObject(page);

page.Canvas.Clear();
page.Width /= 2;
page.Height /= 2;

page.Canvas.DrawXObject(pageXObject, 0, 0, page.Width, page.Height, 0);

pdf.Save("resized.pdf");

矢量图形

Docotic.Pdf 库可以将矢量图形(如线条、曲线和形状)添加到 PDF 文档中。您可以从图形对象构建图形路径。然后,您可以使用不同颜色空间的颜色填充或描边路径。

在示例代码的 图形组 中查找与图形相关的功能的示例代码。

还可以从 PDF 中提取图形。从调用 GetObjects 方法开始,然后从 PdfPageObjectType.Path 类型的对象中提取信息。不要忘记 XObjects 还可以包含嵌套路径。

using var pdf = new PdfDocument("existing.pdf");

var options = new PdfObjectExtractionOptions();
var objects = pdf.Pages[0].GetObjects(options);
foreach (var obj in objects)
{
    if (obj.Type == PdfPageObjectType.Path)
    {
        var path = (PdfPath)obj;
        Console.WriteLine($"Found path {path}");
    }
    else if (obj.Type == PdfPageObjectType.XObject)
    {
        var paintedXObject = (PdfPaintedXObject)obj;
        var nestedObjects = paintedXObject.XObject.GetObjects(options);
        // ...
    }
}

将 HTML 添加到 PDF 页面

将 HTML 内容叠加到 PDF 文档上有助于向 PDF 中添加动态元素,例如图表或股票价格行情。

阅读如何在 PDF 中插入 HTML 以获取更多详细信息并下载示例代码。

编辑 PDF 文本

本节介绍如何编辑 PDF 中的文本、如何更改 PDF 中的文本颜色以及如何添加新文本。

PDF 编辑器更改文本

我们有一篇专门介绍如何从 PDF 中提取文本的文章。查看该文章以获取有关该主题的更多信息。

在 Docotic.Pdf 的帮助下,文本扁平化 也是可能的。

查找和替换

要修改 PDF 中的文本,您需要找到包含文本的区域,然后删除该区域中的文本。最后一步是将新文本添加到文档的同一区域。

搜索 PDF 可能比较棘手,因为文档内部可能包含任何顺序的单词。文本也可能旋转。幸运的是,我们有一个示例代码,展示了 如何在 PDF 中搜索单词或短语

当您有要删除的文本的坐标时,就该编辑包含的页面内容了。该库提供了枚举和复制页面对象的方法。因此,在复制对象时可以省略一些文本。这将从本质上删除文本。编辑 PDF 页面内容 示例的代码显示了该过程的所有细节。您需要更新 ShouldRemoveText 方法以使用找到的坐标。

阅读下一部分,了解如何将新文本添加到文档。

如果您创建带有占位符文本的文档,然后用其他文本替换占位符,则可以使用文本框。

这个想法是向文档添​​加一个没有边框的只读文本框,并将占位符文本放入其中。稍后您可以打开文档,按名称找到文本框,然后用简单的调用box.Text = "new text";替换占位符。如果您不想再做任何更改,请在替换后将文本框展平。

添加新文本

要向文档添加一些文本,请使用PdfCanvas对象的DrawStringDrawText方法。这些方法使用当前画布字体。字体必须包含文本中所有字符的字形。使用PdfFont.ContainsGlyphsForText方法检查字体是否满足此要求。

var canvas = pdf.Pages[0].Canvas;
canvas.Font = pdf.AddFont("NSimSun")
    ?? throw new ArgumentException("Font not found");

canvas.DrawString(10, 50, "Olá. 你好. Hello. This is some new text");

您可以添加使用 Type1、TrueType 和 OpenType 字体绘制的 Unicode 文本。该库可以使用系统上安装的字体、14 种内置 Type1 字体,或者从文件中加载所需的字体。

更改文本颜色

要更改 PDF 中文本的颜色,请使用与 删除文本 相同的方法。您至少需要更改示例代码中的 ReplaceColor 方法。

图片

Docotic.Pdf 提供了编辑 PDF 图像所需的一切。以下是最常用操作的 C# 代码片段。

示例代码的图片组包含本节示例的完整测试项目。

将图像添加到 PDF

该库可以导入 GIF/TIFF/PNG/BMP/JPEG 格式的图像。您还可以从 System.Drawing.Image 对象添加图像。

var canvas = pdf.Pages[0].Canvas;
var image = pdf.AddImage("image.jpg")
    ?? throw new ArgumentException("Cannot add image");

canvas.DrawImage(image, 10, 50);

您可以使用DrawImage方法的重载指定旋转角度和输出大小。要在多个页面上绘制同一图像,请添加一次图像并在对DrawImage方法的多次调用中使用相同的PdfImage对象。

将图像合并为 PDF

以下是 C# 代码,展示如何将多幅图像合并为一个 PDF。

using var pdf = new PdfDocument();

var imagePaths = new string[] { "image.jpg", "another-image.png" };
foreach (var path in imagePaths)
{
    var image = pdf.AddImage(path)
        ?? throw new ArgumentException("Cannot add image");

    var page = pdf.AddPage();
    page.Width = image.Width;
    page.Height = image.Height;

    page.Canvas.DrawImage(image, 0, 0);
}

pdf.RemovePage(0);
pdf.Save("combined-images.pdf");

代码将多张图片添加到 PDF,并更改每页大小以匹配相应的图片大小。在保存结果之前,代码会删除第一个隐式添加的空白页。

提取 PDF 图像

我们设计了 Docotic.Pdf,用于从 PDF 文件中提取图像,而不会损害图像质量。该库不会更改图像大小或压缩。您将获得与 PDF 中质量相同的图像。

using var pdf = new PdfDocument("file-with-images.pdf");
int i = 0;
foreach (PdfImage image in pdf.GetImages())
{
    var path = image.Save($"image{i++}");
    Console.WriteLine($"Saved to {path}");
}

删除和替换图像

使用 PdfPage.RemovePaintedImages 方法从 PDF 页面中删除所有或特定图像。您可以按位置、大小、变换或其他参数过滤图像。

using var pdf = new PdfDocument("file-with-images.pdf");
pdf.Pages[0].RemovePaintedImages(
    image =>
    {
        return image.Size.Width > 100;
    }
);

pdf.RemoveUnusedResources();
pdf.Save("no-wide-images.pdf");

上面的 C# 代码展示了如何在 Docotic.Pdf 的帮助下删除图像。我建议在更改或删除图像后删除未使用的资源。

使用 PdfImage.ReplaceWith 方法替换 PDF 文档中出现的所有图像。

using var pdf = new PdfDocument("file-with-images.pdf");
var firstImage = pdf.GetImages(false).FirstOrDefault()
    ?? throw new ArgumentException("No images found");

firstImage.ReplaceWith("another-image.png");

pdf.RemoveUnusedResources();
pdf.Save("replaced-image.pdf");

更改压缩方案

Docotic.Pdf 提供了更改 PDF 图像压缩的方法。可以使用 JPEG、CCITT Group 3 和 4(传真)、JPEG 2000 和 zip/deflate 压缩算法重新打包图像。

根据初始和新的压缩,这种变化可能会导致细节或图像质量的损失。但有损转换通常有助于减小文档大小

firstImage.RecompressWithJpeg2000(25);

还有其他方法可以重新打包图像。检查名称以RecompressWith开头的PdfImage方法。您可以使用Uncompress方法从图像中删除任何压缩。

调整图像大小

如果 PDF 文档中的某些图像比需要的大,则该库可以为您调整其大小或缩小它们。

firstImage.Scale(0.5, PdfImageCompression.Jpeg2000, 25);

上述代码使第一幅图像在两个方向上都缩小了两倍。该库对生成的图像使用 JPEG 2000 压缩。

您可以使用其中一种 ResizeTo 方法来指定最终宽度和高度的精确值。

调整图像大小通常会比改变压缩率更能减小 PDF 文件的大小(参见上面的部分),但这是一个有损的过程。

水印和背景

PDF 上的水印

为 PDF 添加水印涉及以下步骤:

  • 创建 XObject,即水印内容的容器
  • 用文本、图像和 矢量图形 填充对象
  • 使用对象为 PDF 页面添加水印

以下是向 PDF 添加 Confidential 水印的 C# 代码:

using var pdf = new PdfDocument("existing.pdf");

var watermark = pdf.CreateXObject();
watermark.DrawOnBackground = true;

var canvas = watermark.Canvas;
canvas.FontSize = 72;
canvas.Brush.Color = new PdfRgbColor(222, 35, 35);
canvas.Brush.Opacity = 45;
canvas.Pen.Color = canvas.Brush.Color;
canvas.Pen.Opacity = canvas.Brush.Opacity;
canvas.Pen.Width = 5;

var padding = 10;
var text = "CONFIDENTIAL";
canvas.DrawString(padding, padding, text);

var textSize = canvas.MeasureText(text);
var watermarkRect = new PdfRectangle(
    padding, padding, textSize.Width, textSize.Height);
canvas.DrawRoundedRectangle(watermarkRect, new PdfSize(padding, padding));

foreach (var page in pdf.Pages)
{
    page.Canvas.DrawXObject(
        watermark,
        (page.Width - watermarkRect.Width) / 2,
        (page.Height - watermarkRect.Height) / 2);
}

pdf.Save("watermarked.pdf");

代码设置了水印画布的画笔和钢笔属性。画笔用于绘制文本。为了找出文本大小,代码测量了文本。然后它在文本周围绘制了一个带圆角的矩形。钢笔用于描边矩形。

水印内容准备好后,代码将其绘制在每页的中心。

PDF 背景与水印非常相似。至少您可以用几乎相同的方式创建它们。要向 PDF 添加背景,请执行与上述代码相同的操作,但在CreateXObject调用后添加watermark.DrawOnBackground = true;。请注意,图像等不透明内容可能会遮挡背景。

注解

Docotic.Pdf 为 PDF 中的注释提供了丰富的 API。您可以创建、编辑和删除 PDF 文档中的注释。还可以 扁平化注释

要注释文本,可以使用以下方法:

  • 便签或文本注释。请参阅 PdfPage 类的 AddTextAnnotation 方法。
  • 突出显示。请参阅 AddHighlightAnnotation 方法。
  • 删除线。请参阅 AddStrikeoutAnnotation 方法。
  • 下划线。请参阅 AddJaggedUnderlineAnnotationAddUnderlineAnnotation 方法。

使用链接从一个页面跳转到另一个页面或外部资源。您可以使用墨迹注释在 PDF 页面上进行徒手绘图。对于指定要从文档中删除的部分,有修订注释。您还可以嵌入音频、视频或 3D 内容。

突出显示文本

以下是在 PDF 文档中突出显示文本的方法:

using var pdf = new PdfDocument();

var page = pdf.Pages[0];
var canvas = page.Canvas;
canvas.FontSize = 30;

var text = "Highlighted text.";
var position = new PdfPoint(10, 50);
canvas.DrawString(position, text);
canvas.DrawString(" Not highlighted.");

var size = canvas.MeasureText(text);
var bounds = new PdfRectangle(position, size);

var color = new PdfRgbColor(145, 209, 227);
var annotationText = "Please pay attention to this part.";
page.AddHighlightAnnotation(annotationText, bounds, color);

pdf.Save("highlighted.pdf");

要链接到 PDF 中的特定页面,请使用如下代码:

using var pdf = new PdfDocument();
var secondPage = pdf.AddPage();
secondPage.Canvas.DrawString(10, 50, "Welcome to the second page.");

var firstPage = pdf.Pages[0];
var canvas = firstPage.Canvas;
var linkRect = new PdfRectangle(10, 50, 100, 60);
canvas.DrawRectangle(linkRect, PdfDrawMode.Stroke);

var options = new PdfTextDrawingOptions(linkRect)
{
    HorizontalAlignment = PdfTextAlign.Center,
    VerticalAlignment = PdfVerticalAlign.Center
};
canvas.DrawText("Go to 2nd page", options);

firstPage.AddLinkToPage(linkRect, 1);

pdf.Save("linked.pdf");

在代码中,操作区域注释充当内部超链接。此类区域可以导航到外部资源,也可以执行非导航操作。

删除注释

要从 PDF 中删除注释:

  1. 使用 PdfPage.Widgets 属性或 PdfDocument.GetWidgets 方法访问小部件集合。
  2. 检查类型、属性,或以其他方式确定不再需要哪些注释。
  3. 使用 PdfDocument.RemoveWidget 方法或 PdfWidgetCollection 对象的方法来删除注释。

要从 PDF 中删除附件,您需要删除文件注释和 共享附件

编辑 PDF

作为 PDF 编辑库,Docotic.Pdf 提供从 PDF 文档中永久删除或快速删除敏感信息的方法。

涂黑 PDF 上的信息

编辑文本

以下是如何在没有 Redact 工具的情况下仅使用 C# 和 Docotic.Pdf 来涂黑 PDF 中的文本。

int i = 0;
foreach (var page in pdf.Pages)
{
    foreach (var word in page.GetWords())
    {
        if (i % 3 == 0)
        {
            page.Canvas.AppendRectangle(word.Bounds);
            page.Canvas.FillPath(PdfFillMode.Winding);
        }

        i++;
    }
}

代码在文档中的每个第三个单词上绘制一个黑色矩形。请注意,矩形后面的文本仍保留在文档中,以后可以提取。要永久删除文本,请使用有关 替换文本 的部分中的方法。

删除图片

您也可以使用黑色矩形来覆盖图像。但更简单的方法是用 黑色 1 x 1 像素图像 替换图像。这不仅可以在视觉上突出显示已编辑的图像,还可以删除原始图像数据。

查看有关 删除和替换图像 的部分以获取代码示例。我还建议在替换后调用 PdfDocument.ReplaceDuplicateObjects 方法。

PDF 表单

Docotic.Pdf 可以使用各种交互元素(如按钮、复选框、下拉列表、列表框、单选按钮和文本字段)创建 Acroforms(这是 PDF 表单的另一个名称)。

通常只需几行代码即可添加和设置表单字段。例如,只需调用 PdfPage.AddTextBox 方法即可向 PDF 添加可编辑字段。表单和注释组 中的示例代码提供了有关创建和使用表单的更多信息。

如何填写 PDF 表单

使用 PdfDocument.GetControl 方法通过其完整或部分名称查找 PDF 控件。另一种方法是使用 GetControls 方法枚举文档控件。无论哪种情况,您都需要将控件转换为预期的字段类型。

using var pdf = new PdfDocument(@"example-form.pdf");

if (pdf.GetControl("txt-name") is PdfTextBox nameTextBox)
    nameTextBox.Text = "Bit Miracle team";

if (pdf.GetControl("txt-email") is PdfTextBox emailTextBox)
    emailTextBox.Text = "support@bitmiracle.com";

if (pdf.GetControl("check-agree") is PdfCheckBox agreeCheckBox)
    agreeCheckBox.Checked = true;

pdf.Save("filled-form.pdf");

代码使用这个PDF表单示例。在代码中,我为两个文本字段设置了值并勾选了复选框。

当您填写完表格后,您可以展平所有字段

在表单中使用 JavaScript

您可以添加操作来控制事件。PdfControl 类提供对一组预定义事件的访问。事件的名称以On开头(例如,OnMouseDown)。

以下是使用 JavaScript 制作 PDF 表单的示例:

using var pdf = new PdfDocument(@"example-form.pdf");
foreach (var field in pdf.GetControls())
    field.OnChange = pdf.CreateJavaScriptAction($"app.alert('{field.Name} changed!',3)");

pdf.Save("javascript-events.pdf");

表单数据格式

还有一种以电子方式填写 PDF 的方法。使用库的 FDF 转 PDF 功能从数据库或其他来源自动填充 PDF 表单。

using var pdf = new PdfDocument(@"example-form.pdf");
pdf.ImportFdf("form-data.fdf");
pdf.Save("auto-populated.pdf");

代码使用 此 FDF 文件 一次填充所有表单字段。

拼合 PDF

本节介绍如何扁平化 PDF。

PDF 扁平化

扁平化 PDF 时,您会将表单和注释等交互元素转换为静态内容,以防止进一步编辑。扁平化 PDF 占用的字节数显著减少,但外观相同。

扁平化表单和注释

要扁平化可填写的 PDF,请使用 PdfDocument.FlattenControls 方法。此方法会在其父页面上绘制所有表单字段和其他控件,并从文档中删除源控件。

当您扁平化 PDF 表单时,扁平化注释也是有意义的。使用 PdfDocument.FlattenWidgets 方法可同时扁平化控件和注释。

如果您只想将某些控件和/或注释转换为其视觉表示,请使用 PdfWidget.Flatten 方法。您需要先找到所需的控件 或注释。

扁平化文本

您可以使用 Docotic.Pdf 将 PDF 文本转换为轮廓。这样做的通常原因是为了实现字体独立性。无论是否安装了字体,扁平化的文本在任何设备上看起来都一样。

但是,一旦将文本转换为轮廓,就无法再将其作为文本进行编辑。此外,在扁平化过程中,库会将文本转换为矢量图形。这会增加文件大小。

要拼合 PDF 文本,您需要将文本提取为矢量路径,并将其复制到新页面或同一页面上。有一个 示例代码 可用于此目的。

保存选项

在上面的代码片段中,我使用了没有附加参数的 PdfDocument.Save 方法。在这种情况下,库会使用默认的保存选项。我们精心挑选了默认选项,以便在通常情况下它们可以完美运行。

不过,有些情况下你需要覆盖默认选项。为此,创建一个 PdfSaveOptions 对象,设置选项,并将它们提供给其中一个保存方法。接下来,我将描述这些情况。

使用密码或证书保护 PDF,请创建一个加密处理程序并将其设置为EncryptionHandler属性。

当您想要 多次签署同一个 PDF 时,请通过将 WriteIncrementally 属性设置为 true 来打开增量更新模式。当您使用新注释或表单数据保存先前签署的文件时,请执行相同操作。

Linearize属性设置为true可生成线性化(或针对 Fast Web View 优化)的 PDF 文件。识别此优化的查看器可以更快地显示此类文件。

为了防止保存时对某些 元数据字段 进行更改,请将 UpdateProducerUpdateModifiedDate 属性设置为 false