IRONSOFTWAREHOME
视频

如何应用自定义PDF水印

Curtis Chau
Curtis Chau
Updated: 2026年7月19日

ActivePDF 一直是 .NET 开发人员可靠的 PDF 工具包。 自 2020 年 6 月被收购,并于 2023 年 2 月更名为 Apryse 后,ActivePDF 现在成为 Apryse 更大产品系列中的一个品牌。 本指南提供了从ActivePDF到IronPDF的全面分步迁移路径——这是一个现代的 .NET PDF 库,支持 .NET Framework 4.6.2 到 .NET 9。

为什么要考虑放弃 ActivePDF?

ActivePDF仍然发布,并且ActivePDF.Toolkit NuGet包在Apryse下继续接收更新,但其设计和包装的几个方面可能会让团队评估替代方案。

品牌和路线图考量

ActivePDF 现在是 Apryse 产品中的一个品牌,并且伴随着旗舰 Apryse SDK。 专门选择ActivePDF进行服务器端自动化的团队可能需要权衡是否继续使用ActivePDFSKU,或者随着时间推移转移到更广泛的 Apryse SDK。

许可模式

ActivePDF 的传统按服务器/每核心许可在云和容器化环境中可能会引入摩擦,因为应用程序会跨基础架构动态扩展。

传统架构模式

ActivePDF 的 API 表面反映了其源自 COM/本机的起源。 using、异常和异步相一致。

多 SKU 产品布局

HTML/URL到PDF的渲染存在于单独的ActivePDF.Toolkit中。 从Toolkit 10开始,本机库不再自动复制到系统文件夹,因此构造函数通常需要一个显式的CoreLibPath参数——这种模式可能会使Docker、CI和无安装程序的部署复杂化。

##ActivePDF与 IronPDF:主要区别

在开始迁移过程之前,了解ActivePDF和IronPDF之间的根本区别有助于对所需的代码更改设定预期。

方面ActivePDFIronPDF
供应商Apryse(前身为 PDFTron,于 2020 年 6 月收购 ActivePDF)Iron Software,独立
产品布局多个 SKU(Toolkit, WebGrabber, DocConverter, Server, Meridian)Single IronPdf NuGet package
安装NuGet包 + 本机运行时路径(CoreLibPath 自版本10起)单个 NuGet 包; natives bundled
API模式有状态(CloseOutputFile),COM派生流畅、实用的 API
许可模式每服务器 / 每核心基于代码的关键字
.NET支持.NET Framework 4.5+ / .NET Standard 1.0+ / .NET CoreFramework 4.6.2 到 .NET 9
错误处理整数返回代码(0 = 成功).NET Standard例外情况
支持同步不是本机的完全支持Async/Await

迁移前准备

审核您的代码库

在开始迁移之前,请确定整个解决方案中所有ActivePDF的使用情况。 实际的命名空间是APWebGrabber(WebGrabber); 一些旧项目也通过COM互操作程序集引用ActivePDF.Toolkit。 在解决方案目录中运行这些命令:

grep -r "using APToolkitNET" --include="*.cs" .
grep -r "using APWebGrabber" --include="*.cs" .
grep -r "ActivePDF" --include="*.csproj" .
SHELL

文档破坏性更改

了解 API 的基本差异有助于规划迁移策略:

翻译类别ActivePDF 行为IronPDF 行为迁移行动
产品分拆Toolkit(操作)+ WebGrabber(HTML 渲染)单独出售单个IronPdf将两者合并为一个库
对象模型APWebGrabber.WebGrabber用于HTMLChromePdfRenderer + PdfDocument单独关注
文件操作CloseOutputFile()直接SaveAs()删除打开/关闭调用
本机运行时自版本10起CoreLibPath 参数NuGet 随本机文件发布移除路径配置
页面创建NewPage()方法从 HTML 自动生成删除页面创建调用
返回值整数错误代码例外情况实施 try/catch
页面大小单位点数(612x792 = 字母)枚举或毫米更新测量

前提条件

确保您的环境符合这些要求:

  • .NET Framework 4.6.2+ 或 .NET Core 3.1 / .NET 5-9
  • Visual Studio 2019+ 或 JetBrains Rider
  • 访问 NuGet 包管理器 -IronPDF许可证密钥(可在ironpdf.com免费试用)

逐步迁移过程

步骤 1:更新 NuGet 软件包

在nuget.org上的包是ActivePDF.Toolkit(当前版本11.4.4,发布于2025年12月)。 HTML渲染单独作为ActivePDF.WebGrabber发布。 移除ActivePDFSKU 并安装 IronPDF:

# RemoveActivePDFpackages
dotnet remove package ActivePDF.Toolkit
dotnet remove package ActivePDF.WebGrabber

# Install IronPDF
dotnet add package IronPdf
SHELL

也可通过 Visual Studio 软件包管理器控制台进行翻译:

Uninstall-Package ActivePDF.Toolkit
Uninstall-Package ActivePDF.WebGrabber
Install-Package IronPdf
PowerShell

对于手动DLL引用的项目,从您的.csproj文件中移除引用:

<!-- Remove this block -->
<Reference Include="APToolkitNET">
    <HintPath>path\to\APToolkitNET.dll</HintPath>
</Reference>
XML

步骤 2:配置许可证密钥

在启动应用程序时,在进行任何 PDF 操作前,添加IronPDF许可证密钥:

// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";

// Verify license status
bool isLicensed = IronPdf.License.IsLicensed;

步骤 3:更新命名空间引用

在解决方案中执行全局查找和替换:

查找替换为
using APToolkitNET;using IronPdf;
using APWebGrabber;using IronPdf;
APToolkitNET.ToolkitPdfDocument(操作)
APWebGrabber.WebGrabberChromePdfRenderer

完整的 API 迁移参考

文档创建方法

ActivePDF 方法IronPDF 同等产品备注
new APToolkitNET.Toolkit()new ChromePdfRenderer() / new PdfDocument(...)IronPDF将渲染和操作分开
new Toolkit(CoreLibPath: path)new ChromePdfRenderer()NuGet提供本机——没有CoreLibPath
toolkit.OpenOutputFile(path)无需对等语只需在结束时调用SaveAs
toolkit.CloseOutputFile()无需对等语using负责清理
webGrabber.URL = html; webGrabber.ConvertToPDF()renderer.RenderHtmlAsPdf(html)WebGrabber,而不是 Toolkit
webGrabber.URL = url; webGrabber.ConvertToPDF()renderer.RenderUrlAsPdf(url)WebGrabber,而不是 Toolkit

文件操作

ActivePDF 方法IronPDF 同等产品备注
toolkit.OpenInputFile(path)PdfDocument.FromFile(path)加载现有 PDF
toolkit.MergeFile(path, startPage, endPage)PdfDocument.Merge(pdfs)ActivePDF 合并到打开的输出文件中;IronPDF返回一个新的合并文档
toolkit.NumPages(属性)pdf.PageCount页数
toolkit.GetPageText(page, 0)pdf.Pages[i].Text / pdf.ExtractAllText()文本提取

页面配置

ActivePDF 方法IronPDF 同等产品
toolkit.SetPageSize(612, 792)RenderingOptions.PaperSize = PdfPaperSize.Letter
toolkit.SetOrientation("Landscape")RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
toolkit.SetMargins(t, b, l, r)RenderingOptions.MarginTop/Bottom/Left/Right

安全方法

ActivePDF 方法IronPDF 同等产品
toolkit.SetEncryption(user, owner, 128, 0)pdf.SecuritySettings.OwnerPassword / UserPassword
toolkit.SetPermissions(flags)pdf.SecuritySettings.AllowUserXxx
toolkit.PrintText(x, y, text)(每页水印)pdf.ApplyWatermark(html)

代码迁移示例

HTML 到 PDF 转换

将 HTML 字符串转换为 PDF 文档是最常见的 PDF 生成场景之一。 请注意,在ActivePDF中,HTML 渲染存在于单独许可的 WebGrabber 产品中,而不是 Toolkit 中,并且 WebGrabber 从 URL 或文件路径渲染,而不是从内存中的字符串。

ActivePDF 实现(WebGrabber):

// NuGet: Install-Package ActivePDF.WebGrabber
using APWebGrabber;
using System;
using System.IO;

class Program
{
    static void Main()
    {
        WebGrabber wg = new WebGrabber();

        string htmlContent = "<html><body><h1>Hello World</h1></body></html>";
        string tempHtml = Path.Combine(Path.GetTempPath(), "input.html");
        File.WriteAllText(tempHtml, htmlContent);

        wg.URL = tempHtml;
        wg.OutputDirectory = Directory.GetCurrentDirectory();
        wg.OutputFilename = "output.pdf";

        if (wg.ConvertToPDF() == 0)
        {
            Console.WriteLine("PDF created successfully");
        }
    }
}

IronPDF 实现:

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        
        string htmlContent = "<html><body><h1>Hello World</h1></body></html>";
        
        var pdf = renderer.RenderHtmlAsPdf(htmlContent);
        pdf.SaveAs("output.pdf");
        
        Console.WriteLine("PDF created successfully");
    }
}

IronPDF 方法消除了显式文件句柄管理,同时提供了更简洁、可读性更强的代码。 对于高级从HTML到PDF的情境,IronPDF的ChromePdfRenderer使用Chromium渲染引擎,以实现像素级的CSS和JavaScript支持。

URL到PDF转换

将网页捕获为 PDF 文档也存在于 WebGrabber 中,而不是 Toolkit 中。

ActivePDF 实现(WebGrabber):

// NuGet: Install-Package ActivePDF.WebGrabber
using APWebGrabber;
using System;
using System.IO;

class Program
{
    static void Main()
    {
        WebGrabber wg = new WebGrabber();

        wg.URL = "https://www.example.com";
        wg.OutputDirectory = Directory.GetCurrentDirectory();
        wg.OutputFilename = "webpage.pdf";

        if (wg.ConvertToPDF() == 0)
        {
            Console.WriteLine("PDF from URL created successfully");
        }
    }
}

IronPDF 实现:

using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        
        string url = "https://www.example.com";
        
        var pdf = renderer.RenderUrlAsPdf(url);
        pdf.SaveAs("webpage.pdf");
        
        Console.WriteLine("PDF from URL created successfully");
    }
}

合并多个 PDF 文件

将多个 PDF 文档合并为一个文件展示了IronPDF的文档操作功能方法。

ActivePDF 实现 (Toolkit):

// NuGet: Install-Package ActivePDF.Toolkit
using APToolkitNET;
using System;

class Program
{
    static void Main()
    {
        using (Toolkit toolkit = new Toolkit())
        {
            if (toolkit.OpenOutputFile("merged.pdf") == 0)
            {
                // MergeFile(FileName, StartPage, EndPage); -1 = end of file
                toolkit.MergeFile("document1.pdf", 1, -1);
                toolkit.MergeFile("document2.pdf", 1, -1);
                toolkit.CloseOutputFile();
                Console.WriteLine("PDFs merged successfully");
            }
        }
    }
}

IronPDF 实现:

using IronPdf;
using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        var pdf1 = PdfDocument.FromFile("document1.pdf");
        var pdf2 = PdfDocument.FromFile("document2.pdf");
        
        var merged = PdfDocument.Merge(pdf1, pdf2);
        merged.SaveAs("merged.pdf");
        
        Console.WriteLine("PDFs merged successfully");
    }
}

有关包括选择性页面提取在内的更高级合并方案,请参阅 IronPDF合并文档

添加页眉和页脚

ActivePDF 实现(WebGrabber):

using APWebGrabber;
using System.IO;

public void CreatePdfWithHeaderFooter(string html, string outputPath)
{
    var wg = new WebGrabber();
    string tempHtml = Path.Combine(Path.GetTempPath(), "input.html");
    File.WriteAllText(tempHtml, html);

    wg.URL = tempHtml;
    wg.HeaderText = "My Document";
    wg.FooterText = "Page [page] of [pages]";
    wg.OutputDirectory = Path.GetDirectoryName(outputPath);
    wg.OutputFilename = Path.GetFileName(outputPath);
    wg.ConvertToPDF();
}

IronPDF 实现:

using IronPdf;

public void CreatePdfWithHeaderFooter(string html, string outputPath)
{
    var renderer = new ChromePdfRenderer();

    renderer.RenderingOptions.TextHeader = new TextHeaderFooter
    {
        CenterText = "My Document",
        FontSize = 12,
        FontFamily = "Arial"
    };

    renderer.RenderingOptions.TextFooter = new TextHeaderFooter
    {
        CenterText = "Page {page} of {total-pages}",
        FontSize = 10,
        FontFamily = "Arial"
    };

    using var pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs(outputPath);
}

IronPDF 支持基于文本的页眉和页脚HTML页眉和页脚,提供完全灵活的设计。

密码保护和安全性

ActivePDF 实现 (Toolkit):

using APToolkitNET;

public void ProtectPdf(string inputPath, string outputPath, string password)
{
    using (Toolkit toolkit = new Toolkit())
    {
        if (toolkit.OpenOutputFile(outputPath) == 0
            && toolkit.OpenInputFile(inputPath) == 0)
        {
            toolkit.SetEncryption(password, password, 128, 0);
            toolkit.CopyForm(0, 0);
            toolkit.CloseInputFile();
            toolkit.CloseOutputFile();
        }
    }
}

IronPDF 实现:

using IronPdf;

public void ProtectPdf(string inputPath, string outputPath, string password)
{
    using var pdf = PdfDocument.FromFile(inputPath);

    pdf.SecuritySettings.OwnerPassword = password;
    pdf.SecuritySettings.UserPassword = password;
    pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.FullPrintRights;
    pdf.SecuritySettings.AllowUserCopyPasteContent = false;
    pdf.SecuritySettings.AllowUserEdits = PdfEditSecurity.NoEdit;

    pdf.SaveAs(outputPath);
}

IronPDF 的 安全设置 API 使用强类型枚举而非整数标志对文档权限进行细粒度控制。

文本提取

ActivePDF 实现 (Toolkit):

using APToolkitNET;
using System.Text;

public string ExtractText(string pdfPath)
{
    var sb = new StringBuilder();

    using (Toolkit toolkit = new Toolkit())
    {
        if (toolkit.OpenInputFile(pdfPath) == 0)
        {
            int pageCount = toolkit.NumPages;
            for (int i = 1; i <= pageCount; i++)
            {
                sb.AppendLine(toolkit.GetPageText(i, 0));
            }
            toolkit.CloseInputFile();
        }
    }

    return sb.ToString();
}

IronPDF 实现:

using IronPdf;

public string ExtractText(string pdfPath)
{
    using var pdf = PdfDocument.FromFile(pdfPath);
    return pdf.ExtractAllText();
}

IronPDF 实现将文本提取从多行减少到单个方法调用。

添加水印

ActivePDF 实现 (Toolkit — 每页绘制为页文本):

using APToolkitNET;

public void AddWatermark(string inputPath, string outputPath, string watermarkText)
{
    using (Toolkit toolkit = new Toolkit())
    {
        if (toolkit.OpenOutputFile(outputPath) == 0
            && toolkit.OpenInputFile(inputPath) == 0)
        {
            int pageCount = toolkit.NumPages;
            for (int i = 1; i <= pageCount; i++)
            {
                toolkit.CopyForm(i, 0);
                toolkit.SetFont("Helvetica", 72);
                toolkit.SetTextColor(200, 200, 200);
                toolkit.PrintText(150, 400, watermarkText);
            }
            toolkit.CloseInputFile();
            toolkit.CloseOutputFile();
        }
    }
}

IronPDF 实现:

using IronPdf;

public void AddWatermark(string inputPath, string outputPath, string watermarkText)
{
    using var pdf = PdfDocument.FromFile(inputPath);

    pdf.ApplyWatermark(
        $"<h1 style='color:lightgray;font-size:72px;'>{watermarkText}</h1>",
        rotation: 45,
        opacity: 50);

    pdf.SaveAs(outputPath);
}

IronPDF 的基于 HTML 的水印可通过 CSS 风格实现完全的设计控制,无需逐页迭代。

ASP.NET Core 集成

现代网络应用程序从IronPDF更简洁的集成模式中获益匪浅。

ActivePDF 模式 (WebGrabber):

[HttpPost]
public IActionResult GeneratePdf([FromBody] ReportRequest request)
{
    var wg = new APWebGrabber.WebGrabber();
    string tempHtml = Path.Combine(Path.GetTempPath(), Guid.NewGuid() + ".html");
    System.IO.File.WriteAllText(tempHtml, request.Html);

    wg.URL = tempHtml;
    wg.OutputDirectory = Path.GetTempPath();
    wg.OutputFilename = "temp.pdf";

    if (wg.ConvertToPDF() == 0)
    {
        byte[] bytes = System.IO.File.ReadAllBytes(Path.Combine(Path.GetTempPath(), "temp.pdf"));
        return File(bytes, "application/pdf", "report.pdf");
    }

    return BadRequest("PDF generation failed");
}

IronPDF模式:

[HttpPost]
public IActionResult GeneratePdf([FromBody] ReportRequest request)
{
    var renderer = new ChromePdfRenderer();
    using var pdf = renderer.RenderHtmlAsPdf(request.Html);

    return File(pdf.BinaryData, "application/pdf", "report.pdf");
}

IronPDF 不需要临时文件,直接从内存返回 PDF 二进制数据。

Web 应用程序的同步支持

ActivePDF 缺乏本地异步支持。IronPDF提供可扩展网络应用程序所必需的全部Async/Await功能:

using IronPdf;

public async Task<byte[]> GeneratePdfAsync(string html)
{
    var renderer = new ChromePdfRenderer();
    using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return pdf.BinaryData;
}

依赖注入配置

对于 .NET 6+ 应用程序,请在 DI 容器中注册IronPDF服务:

// Program.cs (.NET 6+)
builder.Services.AddSingleton<ChromePdfRenderer>();

// Service wrapper
public interface IPdfService
{
    Task<byte[]> GeneratePdfAsync(string html);
    Task<byte[]> GeneratePdfFromUrlAsync(string url);
}

public class IronPdfService : IPdfService
{
    private readonly ChromePdfRenderer _renderer;

    public IronPdfService()
    {
        _renderer = new ChromePdfRenderer();
        _renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
    }

    public async Task<byte[]> GeneratePdfAsync(string html)
    {
        using var pdf = await _renderer.RenderHtmlAsPdfAsync(html);
        return pdf.BinaryData;
    }

    public async Task<byte[]> GeneratePdfFromUrlAsync(string url)
    {
        using var pdf = await _renderer.RenderUrlAsPdfAsync(url);
        return pdf.BinaryData;
    }
}

错误处理迁移

ActivePDF 使用整数返回代码,需要查找表。IronPDF使用现代异常处理技术:

ActivePDF 错误处理:

using APToolkitNET;

using (var toolkit = new Toolkit())
{
    int result = toolkit.OpenOutputFile(path);

    if (result != 0)
    {
        // Error - look up the code in "Toolkit Return Results and Error Codes"
        Console.WriteLine($"Error code: {result}");
    }
}

IronPDF 错误处理:

try
{
    var renderer = new ChromePdfRenderer();
    using var pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs(path);
}
catch (IronPdf.Exceptions.IronPdfProductException ex)
{
    Console.WriteLine($"IronPDF Error: {ex.Message}");
}
catch (Exception ex)
{
    Console.WriteLine($"General Error: {ex.Message}");
}

性能优化技巧

重复使用渲染器实例

创建一个新的ChromePdfRenderer有初始化开销。 对于批量操作,请重复使用单个实例:

var renderer = new ChromePdfRenderer();
foreach (var html in htmlList)
{
    using var pdf = renderer.RenderHtmlAsPdf(html);
    pdf.SaveAs($"output_{i}.pdf");
}

在 Web 应用程序中使用异步

对于 ASP.NET Core 应用程序,异步 PDF 生成提高了吞吐量:

public async Task<IActionResult> GenerateReport()
{
    var renderer = new ChromePdfRenderer();
    using var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return File(pdf.BinaryData, "application/pdf");
}

正确的资源处置

始终使用using语句以确保正确的清理:

using var pdf = renderer.RenderHtmlAsPdf(html);
return pdf.BinaryData;

图像压缩

通过图像压缩减少输出文件大小:

using var pdf = renderer.RenderHtmlAsPdf(html);
pdf.CompressImages(85); // 85% quality
pdf.SaveAs("compressed.pdf");

常见迁移问题的故障排除

问题:页面大小差异

ActivePDF 的 WebGrabber 使用点(612x792 = 信函),而IronPDF使用枚举或毫米:

//ActivePDFWebGrabber: Points
wg.PageWidth = 612;
wg.PageHeight = 792;

// IronPDF: Use enum
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
// Or custom in mm:
renderer.RenderingOptions.SetCustomPaperSizeInMillimeters(215.9, 279.4);
C#

问题:缺少 CloseOutputFile 等价函数

IronPDF 使用现代范式,没有明确的文件句柄管理:

//ActivePDFToolkit
toolkit.OpenOutputFile(path);
// ... operations ...
toolkit.CloseOutputFile(); // Required!

//IronPDF- no open/close needed
using var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs(path); // 'using' handles cleanup
C#

问题:PDF 渲染空白

如果依赖 JavaScript 的内容呈现空白,请配置呈现延迟:

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.WaitFor.RenderDelay(2000);
// Or wait for element:
renderer.RenderingOptions.WaitFor.HtmlElementById("content-loaded");

问题:CSS/ 图像无法加载

为相对路径解析配置基本 URL:

renderer.RenderingOptions.BaseUrl = new Uri("https://yourdomain.com/assets/");

迁移后核对表

完成代码迁移后,请验证以下内容:

  • 运行所有现有的单元测试和集成测试
  • 将 PDF 输出结果与以前的版本进行直观比较
  • 在测试环境中测试所有 PDF 工作流程
  • 验证许可是否正常工作(IronPdf.License.IsLicensed
  • 与之前的实现进行基准性能比较
  • 删除旧的ActivePDF安装文件和 DLL 引用
  • 更新 CI/CD 流水线依赖项
  • 为您的开发团队提供IronPDF模式文档

其他资源


从ActivePDF迁移到IronPDF可通过更简洁的 API、更好的 .NET 集成和积极的长期支持使您的 PDF 生成基础架构现代化。 在迁移方面的投资将通过提高代码可维护性、异步功能以及对 PDF 库持续发展的信心而获得回报。

请注意: ActivePDF 和 Apryse 是其各自所有者的注册商标。 本网站与ActivePDF或 Apryse 无关,不被其认可或赞助。 所有产品名称、徽标和品牌均为各自所有者的财产。 比较仅供参考,反映撰写时公开可用的信息。
Curtis Chau
技术作家

Curtis Chau 拥有卡尔顿大学的计算机科学学士学位,专注于前端开发,精通 Node.js、TypeScript、JavaScript 和 React。他热衷于打造直观且美观的用户界面,喜欢使用现代框架并创建结构良好、视觉吸引力强的手册。

...
阅读更多

相关文章

Key in blue circle

立即获取免费的 30 天试用版密钥

Your trial license will be sent to your email address

无任何限制。100% 解锁。无需信用卡。

bullet_checked无需信用卡或创建账户无任何限制。100% 解锁。无需信用卡。
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
预约您的免费现场演示
Booking Badge

深受全球数百万工程师信赖

Iron Software 的客户徽标
获取您的无义务咨询
填写下面的表格或通过sales@ironsoftware.com
您的资料将始终保密。
深受全球数百万工程师信赖
Iron Software 的客户徽标
立即获取您的免费30 天试用密钥
无需信用卡或创建账户