
如何在 .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
授權配置
// 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"' 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" .
完整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.RenderingImports 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 ModuleImports 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 ClassImports 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 ModuleImports 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 ClassImports IronPdf
Class Program
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
pdf.SaveAs("webpage.pdf")
End Sub
End Classpdforge沒有專用的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 ModuleImports 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 ClassImports 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 neededImports 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 neededImports 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: 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
'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: 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: 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: 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' 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")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()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.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"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憑證從配置中移除
- 根據需要新增新功能(合併,水印,安全性)
Curtis Chau擁有Carleton大學的電腦科學學士學位,專精於前端開發,擁有Node.js、TypeScript、JavaScript和React的專業知識。Curtis熱衷於建立直觀且美觀的使用者介面,喜愛使用現代框架並建立結構良好、視覺吸引力的手冊。
相關文章


