如何在 .NET MAUI 中將 XAML 轉換為 PDF
為什麼從pdforge遷移到IronPDF
了解pdforge
pdforge(在2026年重新命名為"pdf noodle"——pdfnoodle.com; api.pdforge.com 主機名將繼續通過301重定向有效至2026年底)是一個基於雲的、模板驅動的PDF生成API,提供了一種通過HTTP調用與您的應用程式整合來生成PDF文件的直觀方式。 NuGet上沒有官方的.NET SDK——整合是通過文件中的REST端點進行的 HttpClient。 通過將建立PDF的任務解除安裝給外部API,開發者可以簡化開發過程。 然而,pdforge存在一些缺點,例如外部依賴、有限的自定義選項以及開發者需注意的持續訂閱成本。
雲端API依賴問題
pdforge在外部雲端伺服器上處理所有文件。 此架構對生產應用程式造成重大關切:
-
外部伺服器處理:每次生成PDF都需要將您的HTML/資料發送到pdforge的伺服器——您的文件會離開您的基礎設施。
-
隱私及合規風險:敏感資料會透過網際網路傳輸到第三方伺服器。 在使用pdforge時,開發者需要考慮與資料發送到外部API相關的安全問題。 如果PDF內容包含敏感資訊,這可能是個關鍵考量。
-
持續訂閱成本:每月費用無限累積,而無資產所有權可言。pdforge的SaaS模式帶來持續的運營支出,這會隨時間而累積。
-
網際網路依賴:當網路不可用時無法生成PDF。
-
速率限制:API使用上限會限制高量應用程式。
- 網路延遲:一次往返時間為每次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正文 { html, pdfParams } |
ChromePdfRenderer + RenderingOptions |
響應:JSON包裹含有signedUrl |
PdfDocument |
返回:signedUrl後) |
pdf.BinaryData |
操作映射
| pdforge | IronPDF |
|---|---|
POST /v1/html-to-pdf/sync 與 { html } |
renderer.RenderHtmlAsPdf(html) |
| 獲取URL,然後POST其HTML(無專用URL端點) | renderer.RenderUrlAsPdf(url) |
下載File.WriteAllBytes(path, bytes) |
pdf.SaveAs(path) |
await http.GetByteArrayAsync(signedUrl) |
pdf.BinaryData |
配置映射
pdforge pdfParams |
IronPDF(RenderingOptions) |
|---|---|
format: "A4" |
renderer.RenderingOptions.PaperSize = PdfPaperSize.A4 |
landscape: true |
renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape |
margin: { top: "20px" } |
renderer.RenderingOptions.MarginTop = 20 |
footerTemplate 與 <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
之後(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
之後(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的主要優勢在於該URL使用Chromium引擎在本地抓取並渲染——沒有資料發送到外部伺服器。 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
之後(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將選項作為JSON字段,作為POST主體內的format = "A4", landscape = true),遵循Chromium/Puppeteer命名慣例。
IronPDF使用renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape。 這提供IntelliSense支援和編譯時型別安全。 注意IronPDF需要導入IronPdf.Rendering命名空間用於紙張大小和方向的列舉。 請參見教程了解更多配置範例。
關鍵遷移注意事項
返回型別變更
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在pdfParams上作為JSON字段傳遞選項; 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的頁眉/頁腳模板格式——包含<span class="..."></span> 元素的HTML片段,渲染時引擎會進行替換。IronPDF在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配置(頁面大小,方向,邊距) - 找出Chromium樣式的頁眉/頁腳模板(
<span class="pageNumber">,{page},{total-pages}) - 規劃IronPDF授權密鑰的儲存(建議使用環境變數)
- 先使用IronPDF試用授權進行測試
套件變更
- pdforge在NuGet上沒有.NET SDK——不需要移除競爭包
- 安裝
IronPdfNuGet包:dotnet add package IronPdf
程式碼變更
- 移除僅用於pdforge調用的
System.Net.Http/System.Text.Json導入 - 新增
using IronPdf;和using IronPdf.Rendering;用於紙張大小和方向列舉 - 使用
HttpClient - 使用
POST /v1/html-to-pdf/sync - 使用
RenderUrlAsPdf()替換獲取URL然後POST的模式 - 使用
GetByteArrayAsync(signedUrl)+File.WriteAllBytes() - 將
RenderingOptions.PaperSize - 將
RenderingOptions.PaperOrientation - 使用
PdfPaperSize.A4/PdfPaperOrientation.Landscape列舉 - 將Chromium模板轉換為
TextHeaderFooter/HtmlHeaderFooter中的IronPDF佔位符 - 用啟動時的一次性
Bearer令牌
遷移後
- 測試PDF輸出質量是否符合預期
- 確認離線操作正常
- 將API憑證從配置中移除
- 根據需要新增新功能(合併,水印,安全性)

