如何在 NET MAUI 中将 XAML 转换为 PDF
为什么要从 pdforge 迁移到 IronPDF?
了解 pdforge
pdforge(在2026年重新命名为"pdf noodle"——pdfnoodle.com; 即使通过301重定向,api.pdforge.com 主机名也会一直有效,直到2026年底)是一个基于云的、模板驱动的PDF生成API,通过HTTP调用集成到您的应用程序中,提供了一种简便的方法来生成PDF文件。 没有在NuGet上提供官方的.NET SDK——集成是通过对记录的REST端点使用HttpClient进行的。 通过将 PDF 创建任务卸载到外部 API,开发人员可以简化开发流程。 不过,pdforge 也存在一些缺点,如外部依赖性、有限的定制选项和持续的订阅成本,开发人员应对此有所了解。
云 API 依赖性问题
pdforge 在外部云服务器上处理所有文件。 这种架构给生产应用程序带来了重大问题:
1.外部服务器处理:您生成的每个 PDF 都需要将您的 HTML/数据发送到 pdforge 的服务器——您的文档将离开您的基础架构。
2.隐私和合规风险:敏感数据通过互联网传输到第三方服务器。 使用 pdforge 时,开发人员需要考虑到与向外部 API 发送数据有关的安全问题。 如果 PDF 内容包含敏感信息,这可能是一个关键的考虑因素。
3.持续订阅成本:每月费用无限期累积,且不涉及资产所有权。pdforge 的 SaaS 模式引入了持续的运营支出,这些支出会随着时间的推移而累积。
4.网络依赖性:网络不可用时无法生成 PDF 文件。
5.速率限制: API 使用上限可能会限制高流量应用程序。
6.网络延迟:往返时间会使每次 PDF 生成增加几秒钟。
pdforge 与IronPDF对比
| 特征 | pdforge | IronPDF |
|---|---|---|
| 部署类型 | 基于云的 API | 本地库 |
| 依赖关系 | 需要互联网和 API 认证 | 无外部依赖性 |
| 定制 | 对 PDF 生成的控制有限 | 完全控制定制 |
| 成本结构 | 持续订阅 | 一次性购买选项 |
| 安全性 | 通过网络发送数据的潜在问题 | 完全在本地环境中进行数据处理 |
| 设置复杂性 | 外部处理使初始设置更简单 | 需要更多的初始设置和配置 |
IronPDF 的与众不同之处在于它提供了一个完全本地化的库,使开发人员能够完全控制 PDF 创建过程。 这对于希望在内部处理文件或外部 API 调用引入安全问题的应用程序尤其有利。IronPDF在本地处理所有内容,将此类风险降至最低。
对于计划在当前.NET版本上采用.NET 10和C# 14的团队,IronPDF提供了一个消除云依赖的本地处理基础,同时增加了全面的PDF操作能力。
开始之前
前提条件
- .NET 环境: .NET Framework 4.6.2+ 或 .NET Core 3.1+ / .NET 5/6/7/8/9+
- NuGet 访问权限:能够安装 NuGet 包
- IronPDF 许可证:请从ironpdf.com获取您的许可证密钥。
NuGet 软件包变更
# pdforge has no official .NET SDK on NuGet — integration is HttpClient + JSON.
# If your project depends only on built-in System.Net.Http, there is no
# competitor package to remove. Just install IronPDF:
dotnet add package IronPdf
# pdforge has no official .NET SDK on NuGet — integration is HttpClient + JSON.
# If your project depends only on built-in System.Net.Http, there is no
# competitor package to remove. Just install IronPDF:
dotnet add package IronPdf
许可配置
// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
// Add at application startup (Program.cs or Startup.cs)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
' Add at application startup (Program.vb or Startup.vb)
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
确定 pdforge 的用法
# Find pdforge / pdf noodle endpoint usage
grep -r "api\.pdforge\.com\|api\.pdfnoodle\.com" --include="*.cs" .
# Find API key / Bearer token references
grep -r "pdfnoodle_api_\|pdforge_api_" --include="*.cs" --include="*.json" --include="*.config" .
# Find Chromium header/footer templates that need migrating
grep -r "totalPages\|pageNumber\|footerTemplate\|headerTemplate" --include="*.cs" .
# Find pdforge / pdf noodle endpoint usage
grep -r "api\.pdforge\.com\|api\.pdfnoodle\.com" --include="*.cs" .
# Find API key / Bearer token references
grep -r "pdfnoodle_api_\|pdforge_api_" --include="*.cs" --include="*.json" --include="*.config" .
# Find Chromium header/footer templates that need migrating
grep -r "totalPages\|pageNumber\|footerTemplate\|headerTemplate" --include="*.cs" .
完整的 API 参考
命名空间变更
// Before: pdforge — raw HttpClient against api.pdfnoodle.com
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
// Before: pdforge — raw HttpClient against api.pdfnoodle.com
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
// After: IronPDF
using IronPdf;
using IronPdf.Rendering;
Imports System.Net.Http
Imports System.Net.Http.Headers
Imports System.Text
Imports System.Text.Json
Imports IronPdf
Imports IronPdf.Rendering
核心概念映射
| pdforge (REST) | IronPDF |
|---|---|
HttpClient + Authorization: Bearer pdfnoodle_api_... |
new ChromePdfRenderer() |
POST https://api.pdfnoodle.com/v1/html-to-pdf/sync |
renderer.RenderHtmlAsPdf(html) |
JSON body { html, pdfParams } |
ChromePdfRenderer + RenderingOptions |
Response: JSON envelope with signedUrl |
PdfDocument |
Return: byte[] (after fetching signedUrl) |
pdf.BinaryData |
操作映射
| pdforge | IronPDF |
|---|---|
POST /v1/html-to-pdf/sync with { html } |
renderer.RenderHtmlAsPdf(html) |
| 获取URL,然后POST其HTML(没有专用的URL端点) | renderer.RenderUrlAsPdf(url) |
Download signedUrl then File.WriteAllBytes(path, bytes) |
pdf.SaveAs(path) |
await http.GetByteArrayAsync(signedUrl) |
pdf.BinaryData |
配置映射
pdforge pdfParams |
IronPDF (渲染选项) |
|---|---|
format: "A4" |
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4 |
landscape: true |
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape |
margin: { top: "20px" } |
renderer.RenderingOptions.MarginTop = 20 |
footerTemplate with <span class="pageNumber"> / <span class="totalPages"> |
TextFooter = new TextHeaderFooter { CenterText = "Page {page} of {total-pages}" } |
pdforge 中没有的新功能
| IronPDF 特点 | 说明 |
|---|---|
PdfDocument.Merge() |
合并多个 PDF |
pdf.ExtractAllText() |
从 PDF 中提取文本 |
pdf.ApplyWatermark() |
添加水印 |
pdf.SecuritySettings |
密码保护 |
pdf.Form |
表格填写 |
pdf.SignWithDigitalSignature() |
数字签名 |
代码迁移示例
示例 1:HTML 字符串到 PDF 的转换
之前(pdforge):
// REST API — no .NET SDK on NuGet. Integration is HttpClient + JSON POST.
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "pdfnoodle_api_YOUR_KEY");
var body = new { html = "<html><body><h1>Hello World</h1></body></html>" };
var json = new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json");
var resp = await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json);
resp.EnsureSuccessStatusCode();
using var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync());
var pdfBytes = await http.GetByteArrayAsync(doc.RootElement.GetProperty("signedUrl").GetString());
File.WriteAllBytes("output.pdf", pdfBytes);
}
}
// REST API — no .NET SDK on NuGet. Integration is HttpClient + JSON POST.
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "pdfnoodle_api_YOUR_KEY");
var body = new { html = "<html><body><h1>Hello World</h1></body></html>" };
var json = new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json");
var resp = await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json);
resp.EnsureSuccessStatusCode();
using var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync());
var pdfBytes = await http.GetByteArrayAsync(doc.RootElement.GetProperty("signedUrl").GetString());
File.WriteAllBytes("output.pdf", pdfBytes);
}
}
Imports System.IO
Imports System.Net.Http
Imports System.Net.Http.Headers
Imports System.Text
Imports System.Text.Json
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Using http As New HttpClient()
http.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Bearer", "pdfnoodle_api_YOUR_KEY")
Dim body = New With {.html = "<html><body><h1>Hello World</h1></body></html>"}
Dim json As New StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json")
Dim resp = Await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json)
resp.EnsureSuccessStatusCode()
Using doc = JsonDocument.Parse(Await resp.Content.ReadAsStringAsync())
Dim pdfBytes = Await http.GetByteArrayAsync(doc.RootElement.GetProperty("signedUrl").GetString())
File.WriteAllBytes("output.pdf", pdfBytes)
End Using
End Using
End Function
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
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");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
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
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
这里的根本区别在于处理模型和返回类型。 pdforge需要经过认证的HttpClient POST到https://api.pdfnoodle.com/v1/html-to-pdf/sync,这将返回一个包含签名的S3 URL的JSON信封——然后您从该URL获取PDF字节并通过File.WriteAllBytes()写入。
IronPDF使用PdfDocument对象。 此对象可以直接通过pdf.BinaryData。 在保存之前,PdfDocument还允许操作(添加水印、与其他PDF合并、添加安全性)。 请参阅 HTML 转 PDF 文档,了解全面的示例。
示例 2:URL 到 PDF 的转换
之前(pdforge):
// REST API — no .NET SDK on NuGet. pdforge has no dedicated URL endpoint;
// fetch the page yourself and POST its HTML to /v1/html-to-pdf/sync.
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "pdfnoodle_api_YOUR_KEY");
var sourceHtml = await http.GetStringAsync("https://example.com");
var body = new { html = sourceHtml };
var json = new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json");
var resp = await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json);
resp.EnsureSuccessStatusCode();
using var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync());
var pdfBytes = await http.GetByteArrayAsync(doc.RootElement.GetProperty("signedUrl").GetString());
File.WriteAllBytes("webpage.pdf", pdfBytes);
}
}
// REST API — no .NET SDK on NuGet. pdforge has no dedicated URL endpoint;
// fetch the page yourself and POST its HTML to /v1/html-to-pdf/sync.
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "pdfnoodle_api_YOUR_KEY");
var sourceHtml = await http.GetStringAsync("https://example.com");
var body = new { html = sourceHtml };
var json = new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json");
var resp = await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json);
resp.EnsureSuccessStatusCode();
using var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync());
var pdfBytes = await http.GetByteArrayAsync(doc.RootElement.GetProperty("signedUrl").GetString());
File.WriteAllBytes("webpage.pdf", pdfBytes);
}
}
Imports System.IO
Imports System.Net.Http
Imports System.Net.Http.Headers
Imports System.Text
Imports System.Text.Json
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Using http As New HttpClient()
http.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Bearer", "pdfnoodle_api_YOUR_KEY")
Dim sourceHtml As String = Await http.GetStringAsync("https://example.com")
Dim body = New With {Key .html = sourceHtml}
Dim json As New StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json")
Dim resp As HttpResponseMessage = Await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json)
resp.EnsureSuccessStatusCode()
Using doc As JsonDocument = JsonDocument.Parse(Await resp.Content.ReadAsStringAsync())
Dim pdfBytes As Byte() = Await http.GetByteArrayAsync(doc.RootElement.GetProperty("signedUrl").GetString())
File.WriteAllBytes("webpage.pdf", pdfBytes)
End Using
End Using
End Function
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
}
}
Imports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
pdf.SaveAs("webpage.pdf")
End Sub
End Class
pdforge没有专用的URL到PDF端点 - 您自己获取页面,然后将其HTML发布到同步端点,并从返回的签名URL下载结果。 IronPDF在PdfDocument。
IronPDF 的主要优势在于使用 Chromium 引擎在本地获取和渲染 URL,而不会将数据发送到外部服务器。IronPDF作为一个本地库,可能会提供更好的性能,因为网络请求不涉及往返时间。 了解有关 URL 至 PDF 转换的更多信息。
示例 3:使用自定义设置将 HTML 文件转换为 PDF 文件
之前(pdforge):
// REST API — no .NET SDK on NuGet. Page size / orientation flow through the
// optional `pdfParams` object using Chromium/Puppeteer-style names.
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "pdfnoodle_api_YOUR_KEY");
var htmlContent = File.ReadAllText("input.html");
var body = new { html = htmlContent, pdfParams = new { format = "A4", landscape = true } };
var json = new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json");
var resp = await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json);
resp.EnsureSuccessStatusCode();
using var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync());
var pdfBytes = await http.GetByteArrayAsync(doc.RootElement.GetProperty("signedUrl").GetString());
File.WriteAllBytes("output.pdf", pdfBytes);
}
}
// REST API — no .NET SDK on NuGet. Page size / orientation flow through the
// optional `pdfParams` object using Chromium/Puppeteer-style names.
using System.IO;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "pdfnoodle_api_YOUR_KEY");
var htmlContent = File.ReadAllText("input.html");
var body = new { html = htmlContent, pdfParams = new { format = "A4", landscape = true } };
var json = new StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json");
var resp = await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json);
resp.EnsureSuccessStatusCode();
using var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync());
var pdfBytes = await http.GetByteArrayAsync(doc.RootElement.GetProperty("signedUrl").GetString());
File.WriteAllBytes("output.pdf", pdfBytes);
}
}
Imports System.IO
Imports System.Net.Http
Imports System.Net.Http.Headers
Imports System.Text
Imports System.Text.Json
Imports System.Threading.Tasks
Module Program
Async Function Main() As Task
Using http As New HttpClient()
http.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Bearer", "pdfnoodle_api_YOUR_KEY")
Dim htmlContent As String = File.ReadAllText("input.html")
Dim body = New With {
.html = htmlContent,
.pdfParams = New With {
.format = "A4",
.landscape = True
}
}
Dim json As New StringContent(JsonSerializer.Serialize(body), Encoding.UTF8, "application/json")
Dim resp As HttpResponseMessage = Await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json)
resp.EnsureSuccessStatusCode()
Using doc As JsonDocument = JsonDocument.Parse(Await resp.Content.ReadAsStringAsync())
Dim pdfBytes As Byte() = Await http.GetByteArrayAsync(doc.RootElement.GetProperty("signedUrl").GetString())
File.WriteAllBytes("output.pdf", pdfBytes)
End Using
End Using
End Function
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
var htmlContent = System.IO.File.ReadAllText("input.html");
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
}
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
class Program
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
var htmlContent = System.IO.File.ReadAllText("input.html");
var pdf = renderer.RenderHtmlAsPdf(htmlContent);
pdf.SaveAs("output.pdf");
}
}
Imports IronPdf
Imports IronPdf.Rendering
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
Dim htmlContent = System.IO.File.ReadAllText("input.html")
Dim pdf = renderer.RenderHtmlAsPdf(htmlContent)
pdf.SaveAs("output.pdf")
End Sub
End Class
本例显示了配置模式的差异。 pdforge在POST体内的format = "A4", landscape = true),遵循Chromium/Puppeteer命名约定。
IronPDF使用强类型枚举的renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape。 这将提供 IntelliSense 支持和编译时类型安全。 请注意,IronPDF需要导入IronPdf.Rendering命名空间以使用纸张大小和方向枚举。 更多配置示例请参见 tutorials 。
关键迁移说明
返回类型更改
pdforge返回带有已签名URL的JSON信封; IronPDF返回PdfDocument:
// pdforge: Two-step — parse signedUrl from JSON, then fetch bytes from it
var resp = await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json);
using var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync());
var pdfBytes = await http.GetByteArrayAsync(doc.RootElement.GetProperty("signedUrl").GetString());
File.WriteAllBytes("output.pdf", pdfBytes);
// IronPDF: Returns PdfDocument
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf"); // Direct save
byte[] bytes = pdf.BinaryData; // Get bytes if needed
// pdforge: Two-step — parse signedUrl from JSON, then fetch bytes from it
var resp = await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json);
using var doc = JsonDocument.Parse(await resp.Content.ReadAsStringAsync());
var pdfBytes = await http.GetByteArrayAsync(doc.RootElement.GetProperty("signedUrl").GetString());
File.WriteAllBytes("output.pdf", pdfBytes);
// IronPDF: Returns PdfDocument
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf"); // Direct save
byte[] bytes = pdf.BinaryData; // Get bytes if needed
Imports System.IO
Imports System.Net.Http
Imports System.Text.Json
Imports IronPdf
' pdforge: Two-step — parse signedUrl from JSON, then fetch bytes from it
Dim resp = Await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json)
Using doc As JsonDocument = JsonDocument.Parse(Await resp.Content.ReadAsStringAsync())
Dim pdfBytes = Await http.GetByteArrayAsync(doc.RootElement.GetProperty("signedUrl").GetString())
File.WriteAllBytes("output.pdf", pdfBytes)
End Using
' IronPDF: Returns PdfDocument
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf") ' Direct save
Dim bytes As Byte() = pdf.BinaryData ' Get bytes if needed
生成器更改
// pdforge: HttpClient against the REST endpoint
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "pdfnoodle_api_YOUR_KEY");
// IronPDF: ChromePdfRenderer
var renderer = new ChromePdfRenderer();
// pdforge: HttpClient against the REST endpoint
using var http = new HttpClient();
http.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", "pdfnoodle_api_YOUR_KEY");
// IronPDF: ChromePdfRenderer
var renderer = new ChromePdfRenderer();
' pdforge: HttpClient against the REST endpoint
Using http As New HttpClient()
http.DefaultRequestHeaders.Authorization = New AuthenticationHeaderValue("Bearer", "pdfnoodle_api_YOUR_KEY")
' IronPDF: ChromePdfRenderer
Dim renderer As New ChromePdfRenderer()
End Using
操作更改
// pdforge operations
await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json); // HTML to PDF
// URL to PDF: fetch the page first, then POST its HTML to the same endpoint
//IronPDFmethods
renderer.RenderHtmlAsPdf(html)
renderer.RenderUrlAsPdf(url)
// pdforge operations
await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json); // HTML to PDF
// URL to PDF: fetch the page first, then POST its HTML to the same endpoint
//IronPDFmethods
renderer.RenderHtmlAsPdf(html)
renderer.RenderUrlAsPdf(url)
' pdforge operations
Await http.PostAsync("https://api.pdfnoodle.com/v1/html-to-pdf/sync", json) ' HTML to PDF
' URL to PDF: fetch the page first, then POST its HTML to the same endpoint
' IronPDF methods
renderer.RenderHtmlAsPdf(html)
renderer.RenderUrlAsPdf(url)
保存方法更改
// pdforge: Two-step — fetch bytes from signed URL, then write to disk
var pdfBytes = await http.GetByteArrayAsync(signedUrl);
File.WriteAllBytes("output.pdf", pdfBytes);
// IronPDF: Built-in save method
pdf.SaveAs("output.pdf");
// pdforge: Two-step — fetch bytes from signed URL, then write to disk
var pdfBytes = await http.GetByteArrayAsync(signedUrl);
File.WriteAllBytes("output.pdf", pdfBytes);
// IronPDF: Built-in save method
pdf.SaveAs("output.pdf");
' pdforge: Two-step — fetch bytes from signed URL, then write to disk
Dim pdfBytes = Await http.GetByteArrayAsync(signedUrl)
File.WriteAllBytes("output.pdf", pdfBytes)
' IronPDF: Built-in save method
pdf.SaveAs("output.pdf")
配置位置更改
pdforge将选项作为JSON字段传递到pdfParams;IronPDF使用 RenderingOptions:
// pdforge: JSON pdfParams object on the POST body
var body = new { html, pdfParams = new { format = "A4", landscape = true } };
// IronPDF: Properties on RenderingOptions
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
// pdforge: JSON pdfParams object on the POST body
var body = new { html, pdfParams = new { format = "A4", landscape = true } };
// IronPDF: Properties on RenderingOptions
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
' pdforge: JSON pdfParams object on the POST body
Dim body = New With {Key .html = html, Key .pdfParams = New With {Key .format = "A4", Key .landscape = True}}
' IronPDF: Properties on RenderingOptions
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
页眉/页脚占位符语法
pdforge继承了Chromium的页眉/页脚模板格式——HTML片段包含的TextHeaderFooter / HtmlHeaderFooter内:
// pdforge: Chromium template HTML inside pdfParams.footerTemplate
// "<div>Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span></div>"
//IronPDFplaceholders
"Page {page} of {total-pages}" // Note: hyphen in total-pages
// pdforge: Chromium template HTML inside pdfParams.footerTemplate
// "<div>Page <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span></div>"
//IronPDFplaceholders
"Page {page} of {total-pages}" // Note: hyphen in total-pages
' pdforge: Chromium template HTML inside pdfParams.footerTemplate
' "<div>Page <span class=""pageNumber""></span> of <span class=""totalPages""></span></div>"
' IronPDFplaceholders
"Page {page} of {total-pages}" ' Note: hyphen in total-pages
迁移后的新功能
迁移到IronPDF后,您将获得 pdforge 无法提供的功能:
PDF 合并
var pdf1 = PdfDocument.FromFile("document1.pdf");
var pdf2 = PdfDocument.FromFile("document2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
var pdf1 = PdfDocument.FromFile("document1.pdf");
var pdf2 = PdfDocument.FromFile("document2.pdf");
var merged = PdfDocument.Merge(pdf1, pdf2);
merged.SaveAs("merged.pdf");
Dim pdf1 = PdfDocument.FromFile("document1.pdf")
Dim pdf2 = PdfDocument.FromFile("document2.pdf")
Dim merged = PdfDocument.Merge(pdf1, pdf2)
merged.SaveAs("merged.pdf")
文本提取
var pdf = PdfDocument.FromFile("document.pdf");
string allText = pdf.ExtractAllText();
var pdf = PdfDocument.FromFile("document.pdf");
string allText = pdf.ExtractAllText();
Dim pdf = PdfDocument.FromFile("document.pdf")
Dim allText As String = pdf.ExtractAllText()
水印
pdf.ApplyWatermark("<h2 style='color:red;'>CONFIDENTIAL</h2>");
pdf.ApplyWatermark("<h2 style='color:red;'>CONFIDENTIAL</h2>");
pdf.ApplyWatermark("<h2 style='color:red;'>CONFIDENTIAL</h2>")
密码保护
pdf.SecuritySettings.UserPassword = "userpassword";
pdf.SecuritySettings.OwnerPassword = "ownerpassword";
pdf.SecuritySettings.UserPassword = "userpassword";
pdf.SecuritySettings.OwnerPassword = "ownerpassword";
pdf.SecuritySettings.UserPassword = "userpassword"
pdf.SecuritySettings.OwnerPassword = "ownerpassword"
功能对比摘要
| 特征 | pdforge | IronPDF |
|---|---|---|
| HTML 至 PDF | ✓ | ✓ |
| URL 至 PDF | ✓ | ✓ |
| 页面设置 | ✓ | ✓ |
| 离线能力 | ✗ | ✓ |
| 本地处理 | ✗ | ✓ |
| 合并 PDF | ✗ | ✓ |
| 拆分 PDF | ✗ | ✓ |
| 提取文本 | ✗ | ✓ |
| 水印 | ✗ | ✓ |
| 表格填写 | ✗ | ✓ |
| 数字签名 | ✗ | ✓ |
| 密码保护 | ✗ | ✓ |
| 无费率限制 | ✗ | ✓ |
| 一次性许可 | ✗ | ✓ |
迁移清单
迁移前
- 清点代码库中所有pdforge / pdf noodle端点调用(
api.pdforge.com,api.pdfnoodle.com) - 记录使用的当前
pdfParamsJSON配置(页面大小、方向、页边距) - 确定要转换为IronPDF占位符(
{page},<span class="pageNumber">,<span class="totalPages">) - 规划IronPDF许可证密钥存储(建议使用环境变量)
- 先使用IronPDF试用许可证进行测试
软件包变更
- pdforge在NuGet上没有.NET SDK — 没有竞争对手包需要删除
- 安装
IronPdfNuGet包:dotnet add package IronPdf
代码更改
- 删除仅用于pdforge调用的
System.Net.Http/System.Text.Json导入 - 添加
using IronPdf.Rendering;以用于纸张大小和方向枚举 - 将经过认证的
ChromePdfRenderer - 用
POST /v1/html-to-pdf/sync - 将获取URL然后POST模式替换为
RenderUrlAsPdf() - 将两步的
GetByteArrayAsync(signedUrl)+pdf.SaveAs() - 将
RenderingOptions.PaperSize - 将
RenderingOptions.PaperOrientation - 使用
PdfPaperSize.A4/PdfPaperOrientation.Landscape枚举 - 将Chromium模板转换为IronPDF占位符放入
TextHeaderFooter/HtmlHeaderFooter - 在启动时用一次性
Bearer标记
后迁移
- 测试 PDF 输出质量是否符合预期
- 验证离线操作是否正常
- 从配置中移除 API 凭据
- 根据需要添加新功能(合并、水印、安全)。

