如何使用 C# 在 PDF 中编辑文本和区域
从PeachPDF迁移到IronPDF可获得企业级 PDF 生成功能、积极开发和专业支持。 本指南提供了一个逐步迁移路径,帮助您从PeachPDF的1.0之前的异步HTML到PDF工作流转向支持Chromium渲染、安全设置和文档操作API的功能更丰富的PDF解决方案。
为什么要从PeachPDF迁移到 IronPDF.
了解 PeachPDF
PeachPDF 是 .NET 生态系统中一个相对较新的产品,专为需要将 HTML 转换为 PDF 的开发人员设计。 作为一个库,PeachPDF 承诺采用纯粹的 .NET 实现,不依赖外部进程,确保可以在支持 .NET 的平台上无缝集成。 这一特点使PeachPDF成为寻找轻量级管理库解决方案的项目的理想选择。
尽管潜力巨大,但PeachPDF仍处于开发阶段,既有令人兴奋的可能性,也有显著的局限性。PeachPDF因其纯粹的 .NET Core 而极具吸引力,可在各种环境中直接部署。 然而,这也意味着采用率有限,用户群和社区驱动的支持较少。
###PeachPDF的局限性
PeachPDF 是一个单一维护者的、未达到1.0版本的 .NET 库(最新 0.7.26,2025年10月),根据BSD-3-Clause由 jhaygood86 发布。 它缺乏成熟度、功能和现有解决方案的支持。 迁移的主要原因:
-
**1.0之前的功能集:**PeachPDF没有内置的数字签名、PDF/A合规性、OCR、表单填写或页面级页眉/页脚API。
-
**无JavaScript引擎:**PeachPDF是一个基于
PeachPDF.PdfSharpCore构建的布局渲染器,而不是一个浏览器; 脚本和复杂的Grid/Flexbox布局无法执行。 -
仅限
net8.0: 该软件包目标是net8.0; 较旧的.NET Framework/.NET 6项目需要升级或选择不同的库。 -
**小型社区:**单一GitHub维护者,有限的文档,有限的示例。
-
**无企业支持:**没有商业支持或SLA选项。
###PeachPDF与IronPDF对比
| 功能/特点 | PeachPDF | IronPDF |
|---|---|---|
| 实施 | 纯托管 .NET(在 PeachPDF.PdfSharpCore + SixLabors 上) | 托管嵌入式Chromium运行时 |
| 许可 | BSD-3-Clause | 商业翻译 |
| 目标框架 | net8.0 仅限 | .NET Framework 4.6.2+, .NET 6/7/8 |
| 用户群 | 小型(未达1.0版本,0.7.26 于2025年10月发布) | 大型项目 |
| 支持 | 社区驱动(单一维护者,jhaygood86) | 专业,提供专门支持 |
| HTML 渲染 | 基于PdfSharpCore的HTML+CSS布局引擎 | 完整的 Chromium |
| CSS支持 | HTML+CSS 子集,网页字体,@font-face | 完整的 CSS3 |
| JavaScript语言 | 不执行 | 完整的 ES2024 |
| 数字签名 | 否 | 是 |
| PDF/A合规性 | 否 | 是 |
| 文档 | 有限(单一README) | 广泛 |
| 开发状态 | 未达1.0版本(0.7.26,2025年10月) | 成熟、稳定的版本 |
IronPDF 凭借更广泛的功能脱颖而出,不仅支持 HTML 到 PDF 的转换,还支持 OCR、水印和其他高级功能。 其专业支持结构提供快速解决开发者遇到问题的路径。
对于采用现代.NET的团队,IronPDF提供全面的功能和积极的维护,以支持当前.NET版本的长期稳定性。
开始之前
前提条件
- .NET 环境: .NET Framework 4.6.2+ 或 .NET Core 3.1+ / .NET 5/6/7/8/9+
- **NuGet 访问权限:**能够安装 NuGet 包
- **IronPDF 许可证:**请从ironpdf.com获取您的许可证密钥。
NuGet 软件包变更
# Remove PeachPDF
dotnet remove package PeachPDF
# Install IronPDF
dotnet add package IronPdf
许可配置
// Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";' Add at application startup
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"确定PeachPDF的用途
# AuditPeachPDFusage in codebase
grep -r "using PeachPDF" --include="*.cs" .
grep -r "PdfGenerator\|PdfGenerateConfig\|GeneratePdf" --include="*.cs" .
完整的 API 参考
命名空间变更
// Before: PeachPDF
using PeachPDF;
using PeachPDF.PdfSharpCore;
using System.IO;
using System.Threading.Tasks;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;Imports IronPdf
Imports IronPdf.Rendering
Imports System.IO
Imports System.Threading.Tasks核心 API 映射
| PeachPDF | IronPDF |
|---|---|
new PdfGenerator() | new ChromePdfRenderer() |
await generator.GeneratePdf(html, config) | renderer.RenderHtmlAsPdf(html) |
document.Save(stream) | pdf.SaveAs(path) |
document.Save(memStream) 然后 memStream.ToArray() | pdf.BinaryData |
new PdfGenerateConfig { NetworkAdapter = new HttpClientNetworkAdapter(...) } | renderer.RenderUrlAsPdf(url) |
config.PageSize, config.PageOrientation | renderer.RenderingOptions.PaperSize, .PaperOrientation |
嵌入源 HTML(CSS position: fixed) | RenderingOptions.HtmlHeader / HtmlFooter |
| 不支持 | PdfDocument.FromFile(path) |
| 不支持 | PdfDocument.Merge(pdfs) / pdf.AppendPdf(...) |
代码迁移示例
示例 1:HTML 字符串到 PDF 的转换
之前 (PeachPDF):
using PeachPDF;
using PeachPDF.PdfSharpCore;
using System.IO;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var html = "<html><body><h1>Hello World</h1></body></html>";
var config = new PdfGenerateConfig
{
PageSize = PageSize.Letter,
PageOrientation = PageOrientation.Portrait
};
var generator = new PdfGenerator();
var document = await generator.GeneratePdf(html, config);
using var stream = File.Create("output.pdf");
document.Save(stream);
}
}Imports PeachPDF
Imports PeachPDF.PdfSharpCore
Imports System.IO
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Dim html As String = "<html><body><h1>Hello World</h1></body></html>"
Dim config As New PdfGenerateConfig With {
.PageSize = PageSize.Letter,
.PageOrientation = PageOrientation.Portrait
}
Dim generator As New PdfGenerator()
Dim document = Await generator.GeneratePdf(html, config)
Using stream As FileStream = File.Create("output.pdf")
document.Save(stream)
End Using
End Function
End ModuleAfter (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var html = "<html><body><h1>Hello World</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
}
}Imports IronPdf
Imports System
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim html = "<html><body><h1>Hello World</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
End Sub
End Class此示例展示了两个库之间的根本区别。PeachPDF将 PdfGenerator(引擎)与 PdfGenerateConfig(设置)分离,提供一个异步 GeneratePdf 方法,并返回一个文档,其 Save 方法写入到 Stream。IronPDF使用 ChromePdfRenderer 和 RenderHtmlAsPdf(),返回一个带有内置 SaveAs() 方法的 PdfDocument 对象。
IronPDF 的方法的一个实际优势是: PdfDocument 对象可以在保存前进一步处理(添加水印、合并、安全设置),而 SaveAs 可以直接接受文件路径,而无需中间的 FileStream。 更多示例请参阅HTML到PDF文档。
示例 2:URL 到 PDF 的转换
之前 (PeachPDF):
//PeachPDFhas no ConvertUrl-style helper; URL fetching is wired via
// HttpClientNetworkAdapter and passing null HTML so the engine fetches the page.
using PeachPDF;
using PeachPDF.Network;
using PeachPDF.PdfSharpCore;
using System;
using System.IO;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var http = new HttpClient();
var config = new PdfGenerateConfig
{
PageSize = PageSize.Letter,
NetworkAdapter = new HttpClientNetworkAdapter(http, new Uri("https://www.example.com"))
};
var generator = new PdfGenerator();
var document = await generator.GeneratePdf(null, config);
using var stream = File.Create("webpage.pdf");
document.Save(stream);
}
}
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var url = "https://www.example.com";
var pdf = renderer.RenderUrlAsPdf(url);
pdf.SaveAs("webpage.pdf");
}
}Imports IronPdf
Imports System
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim url = "https://www.example.com"
Dim pdf = renderer.RenderUrlAsPdf(url)
pdf.SaveAs("webpage.pdf")
End Sub
End ClassPeachPDF没有一流的URL到PDF助手; 您将配置中的 NetworkAdapter 设置为 HttpClientNetworkAdapter,并传递 null HTML,以便引擎获取页面。IronPDF直接暴露 RenderUrlAsPdf(url)。 由于PeachPDF不执行JavaScript,单页应用程序和动态内容通常无法通过网络适配器路径正确渲染; IronPDF的Chromium引擎处理现代CSS和JavaScript。 在我们的教程中了解更多信息。
示例 3:添加页眉和页脚
之前 (PeachPDF):
//PeachPDFv0.7.x has no header/footer API. The closest approach is
// to embed the header/footer markup directly inside the source HTML
// using CSS positioning.
using PeachPDF;
using PeachPDF.PdfSharpCore;
using System.IO;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var html = @"
<html><head><style>
.header { position: fixed; top: 0; left: 0; right: 0; text-align:center; }
.footer { position: fixed; bottom: 0; left: 0; right: 0; text-align:center; }
</style></head>
<body>
<div class='header'>My Header</div>
<h1>Document Content</h1>
<div class='footer'>Footer text</div>
</body></html>";
var config = new PdfGenerateConfig { PageSize = PageSize.Letter };
var generator = new PdfGenerator();
var document = await generator.GeneratePdf(html, config);
using var stream = File.Create("document.pdf");
document.Save(stream);
}
}
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter() { HtmlFragment = "<div style='text-align:center'>My Header</div>" };
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter() { HtmlFragment = "<div style='text-align:center'>Page {page}</div>" };
var html = "<html><body><h1>Document Content</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("document.pdf");
}
}Imports IronPdf
Imports IronPdf.Rendering
Imports System
Module Program
Sub Main()
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.HtmlHeader = New HtmlHeaderFooter() With {.HtmlFragment = "<div style='text-align:center'>My Header</div>"}
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter() With {.HtmlFragment = "<div style='text-align:center'>Page {page}</div>"}
Dim html As String = "<html><body><h1>Document Content</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("document.pdf")
End Sub
End Module本例显示了一个关键的架构差异。PeachPDF在 PdfGenerator 或 PdfGenerateConfig 上不暴露页眉/页脚 API,因此页面的样式需要使用 CSS 定位在源 HTML 内部。IronPDF使用分配给 RenderingOptions.HtmlHeader 和 RenderingOptions.HtmlFooter 的 HtmlHeaderFooter 对象,将页面样式从文档内容中分开。
IronPDF 方法还暴露类似 MaxHeight 的属性来控制页眉/页脚的大小,并支持用于页码的 {page} 和 {total-pages} 占位符。
注意IronPDF需要的额外命名空间: using IronPdf.Rendering;,用于 HtmlHeaderFooter 类。
关键迁移说明
生成器/渲染器类更改
PeachPDF 使用 PdfGenerator + PdfGenerateConfig 对;IronPDF使用单个 ChromePdfRenderer:
// PeachPDF
var config = new PdfGenerateConfig { PageSize = PageSize.Letter };
var generator = new PdfGenerator();
// IronPDF
var renderer = new ChromePdfRenderer();' PeachPDF
Dim config As New PdfGenerateConfig With {.PageSize = PageSize.Letter}
Dim generator As New PdfGenerator()
' IronPDF
Dim renderer As New ChromePdfRenderer()异步与同步,以及返回类型
PeachPDF 的 GeneratePdf 只能异步操作,并返回一个其 Save 方法接受 Stream 的文档。IronPDF的 RenderHtmlAsPdf 是同步的(也提供 RenderHtmlAsPdfAsync 的异步版本)并返回一个 PdfDocument:
// PeachPDF: async, save to a Stream
var document = await generator.GeneratePdf(html, config);
using var fs = File.Create("output.pdf");
document.Save(fs);
// IronPDF: synchronous PdfDocument object
PdfDocument pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// Or get bytes: byte[] bytes = pdf.BinaryData;Imports System.IO
' PeachPDF: async, save to a Stream
Dim document = Await generator.GeneratePdf(html, config)
Using fs As FileStream = File.Create("output.pdf")
document.Save(fs)
End Using
' IronPDF: synchronous PdfDocument object
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
' Or get bytes: Dim bytes As Byte() = pdf.BinaryData页眉/页脚属性更改
// PeachPDF: no header/footer API -- embed in source HTML
// (e.g. via CSS position:fixed)
// IronPDF: HtmlHeaderFooter objects
renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter()
{
HtmlFragment = "<div>Header</div>"
};
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter()
{
HtmlFragment = "<div>Footer</div>"
};' PeachPDF: no header/footer API -- embed in source HTML
' (e.g. via CSS position:fixed)
' IronPDF: HtmlHeaderFooter objects
renderer.RenderingOptions.HtmlHeader = New HtmlHeaderFooter() With {
.HtmlFragment = "<div>Header</div>"
}
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter() With {
.HtmlFragment = "<div>Footer</div>"
}方法名称更改
| PeachPDF | IronPDF |
|---|---|
await generator.GeneratePdf(html, config) | renderer.RenderHtmlAsPdf(html) |
NetworkAdapter = new HttpClientNetworkAdapter(...) + GeneratePdf(null, config) | renderer.RenderUrlAsPdf(url) |
document.Save(stream) | pdf.SaveAs(path) |
迁移后的新功能
迁移到IronPDF后,您将获得PeachPDF无法提供的功能:
PDF 合并
var pdf1 = PdfDocument.FromFile("doc1.pdf");
var pdf2 = PdfDocument.FromFile("doc2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
使用 HTML 的水印
var pdf = PdfDocument.FromFile("document.pdf");
pdf.ApplyWatermark("<div style='color: red; font-size: 48pt;'>DRAFT</div>");
pdf.SaveAs("watermarked.pdf");Dim pdf = PdfDocument.FromFile("document.pdf")
pdf.ApplyWatermark("<div style='color: red; font-size: 48pt;'>DRAFT</div>")
pdf.SaveAs("watermarked.pdf")密码保护
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Confidential</h1>");
pdf.SecuritySettings.OwnerPassword = "owner123";
pdf.SecuritySettings.UserPassword = "user123";
pdf.SecuritySettings.AllowUserCopyPasteContent = false;
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint;
pdf.SaveAs("protected.pdf");Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Confidential</h1>")
pdf.SecuritySettings.OwnerPassword = "owner123"
pdf.SecuritySettings.UserPassword = "user123"
pdf.SecuritySettings.AllowUserCopyPasteContent = False
pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint
pdf.SaveAs("protected.pdf")数字签名
using IronPdf.Signing;
var pdf = PdfDocument.FromFile("document.pdf");
var signature = new PdfSignature("certificate.pfx", "password")
{
SigningReason = "Document Approval",
SigningLocation = "New York"
};
pdf.Sign(signature);
pdf.SaveAs("signed.pdf");Imports IronPdf.Signing
Dim pdf = PdfDocument.FromFile("document.pdf")
Dim signature = New PdfSignature("certificate.pfx", "password") With {
.SigningReason = "Document Approval",
.SigningLocation = "New York"
}
pdf.Sign(signature)
pdf.SaveAs("signed.pdf")异步操作
var renderer = new ChromePdfRenderer();
var pdf = await renderer.RenderHtmlAsPdfAsync("<h1>Async PDF</h1>");
pdf.SaveAs("async_output.pdf");Dim renderer As New ChromePdfRenderer()
Dim pdf = Await renderer.RenderHtmlAsPdfAsync("<h1>Async PDF</h1>")
pdf.SaveAs("async_output.pdf")功能对比摘要
| 特征 | PeachPDF | IronPDF |
|---|---|---|
| HTML 至 PDF | 基于PdfSharpCore的布局 | 完整的 Chromium |
| URL 至 PDF | 通过 HttpClientNetworkAdapter(无 JS) | 是 |
| CSS 网格/Flexbox | 部分支持/不保证 | 是 |
| JavaScript | 不执行 | 完整的 ES2024 |
| 合并 PDF | 否(仅HTML->PDF) | 是 |
| 拆分 PDF | 否 | 是 |
| 水印 | 通过HTML手动 | 完整的 HTML |
| 页眉/页脚 | 通过HTML/CSS手动 | 完整的 HTML |
| 数字签名 | 否 | 是 |
| PDF/A | 否 | 是 |
| 表格填写 | 否 | 是 |
| 文本提取 | 否 | 是 |
| 图像提取 | 否 | 是 |
| 异步支持 | 仅异步API | 是 |
| 跨平台 | net8.0(Windows / Linux / macOS) | 是 |
常见迁移问题
问题 1:不同的 API 模式
**问题:**PeachPDF将 PdfGenerator(引擎)与 PdfGenerateConfig(设置)分离并异步;IronPDF使用一个 ChromePdfRenderer,同步返回一个 PdfDocument。
解决方案:
//PeachPDFpattern (async, stream-out)
var config = new PdfGenerateConfig { PageSize = PageSize.Letter };
var generator = new PdfGenerator();
var document = await generator.GeneratePdf(html, config);
using var fs = File.Create(path);
document.Save(fs);
//IronPDFpattern
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs(path);
问题 2:目标为流而非路径的保存
**问题:**PeachPDF的 document.Save(stream) 仅接受 Stream;IronPDF的 pdf.SaveAs(path) 接受路径字符串。
解决方案: 在IronPDF中直接使用 pdf.SaveAs("file.pdf") ,而不是打开 FileStream。
问题 3:无现有 PDF 操作
**问题:**PeachPDF 仅支持 HTML 转 PDF; 它无法加载、合并、拆分或编辑现有的 PDF。
解决方案: 替换这些操作为IronPDF的 PdfDocument.Merge 和 pdf.AppendPdf 一旦迁移。
迁移清单
迁移前
- 审核代码库中PeachPDF的使用情况
- 记录自定义配置
- 注意所有页眉/页脚的实现方式
- 从ironpdf.com获取IronPDF许可证密钥
- 先使用IronPDF试用许可证进行测试
软件包变更
- 移除
PeachPDFNuGet 包 - 安装
IronPdfNuGet 包:dotnet add package IronPdf
代码更改
- 更新命名空间导入(
using PeachPDF;→using IronPdf;) - 添加
using IronPdf.Rendering;用于页眉/页脚功能 - 替换
PdfGenerator+PdfGenerateConfig为ChromePdfRenderer - 替换
await generator.GeneratePdf(html, config)为renderer.RenderHtmlAsPdf(html)(或者RenderHtmlAsPdfAsync以维持异步) - 替换
HttpClientNetworkAdapter+GeneratePdf(null, config)为renderer.RenderUrlAsPdf(url) - 替换
document.Save(stream)为pdf.SaveAs(path) - 用
HtmlFooter对象替换嵌入 HTML 中的页眉/页脚 - 在应用程序启动时添加许可证初始化
后迁移
- 测试 HTML 渲染质量
- 验证 PDF 输出是否符合预期
- 测试带有页码的页眉/页脚渲染效果
- 根据需要添加新功能(安全、水印、合并)
PeachPDF是其各自所有者的注册商标。 本网站与PeachPDF无关联、无背书或受PeachPDF赞助。 所有产品名称、徽标和品牌均为各自所有者的财产。 比较仅供参考,反映撰写时公开可用的信息。)}]

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