如何用 C# 從 Gotenberg 轉移到 IronPDF
從高登堡轉移到IronPDF可將您的 .NET PDF 工作流程從基於 Docker 的微服務架構與 HTTP API 呼叫轉換為流程中的本機 C# 函式庫。 本指南提供了一個全面、循序漸進的遷移路徑,可為專業的 .NET 開發人員消除基礎架構開銷、網路延遲和容器管理的複雜性。
為什麼要從高登堡轉移到 IronPDF?
高登堡架構問題
Gotenberg 是基於 Docker 的 PDF 生成微服務架構。 雖然功能強大且靈活,但卻為 C# 應用程式帶來顯著的複雜性:
1.基礎架構開銷:需要 Docker、容器編排(Kubernetes/Docker Compose)、服務發現和負載平衡。 每次部署都會變得更加複雜。
2.網路延遲:每次 PDF 操作都需要向單獨的服務發起 HTTP 請求,每次請求會增加 10-100 毫秒以上的延遲。在高流量場景下,這種延遲會迅速累積。
3.冷啟動問題:容器啟動可能會為首次請求增加 2-5 秒的時間。 每次 pod 重新啟動、每次擴充事件以及每次部署都會觸發冷啟動。
4.操作複雜性:您必須將容器健康狀況、擴充功能、日誌記錄和監控作為與主應用程式分開的獨立問題進行管理。
5.多部分錶單資料:每個請求都需要建立 multipart/form-data 有效負載-冗長、容易出錯且難以維護。
6.故障點:網路逾時、服務不可用和容器崩潰等問題都需要您負責處理。
7.版本管理:高登堡圖片的更新與您的應用程式是分開的; API 變更可能會意外地破壞整合。
高登堡與IronPDF的比較
| 範疇 | 高登堡 | IronPDF |
|---|---|---|
| 部署 | Docker 容器 + 協調 | 單一 NuGet 套件 |
| 架構 | 微服務 (REST API) | 處理中的資料庫 |
| 每次請求的延遲時間 | 10-100ms+ (網路往返) | < 1ms 開銷 |
| 冷启動 | 2-5 秒 (容器啟動) | 1-2 秒 (僅限第一次渲染) |
| 基礎架構 | Docker、Kubernetes、負載平衡器 | 無要求 |
| 失敗模式 | 網路、容器、服務故障 | 標準的 .NET 例外情況 |
| API 風格 | REST multipart/form-data | 原生 C# 方法呼叫 |
| 縮放 | 橫向(更多容器) | 垂直 (處理中) |
| 調試 | 需要分散式追蹤 | 標準除錯器 |
| 版本控制 | 容器影像標籤 | NuGet 套件版本 |
對於計劃在 2025 年和 2026 年之前採用 .NET 10 和 C# 14 的團隊而言,IronPDF 提供了一個面向未來的基礎,零基礎結構依賴性,可與現代 .NET 模式原生整合。
遷移複雜性評估
按功能估計的工作量
| 特點 | 遷移複雜性 |
|---|---|
| HTML 至 PDF | 非常低 |
| URL 至 PDF | 非常低 |
| 自訂紙張尺寸 | 低 |
| 邊際 | 低 |
| PDF 合併 | 低 |
| 頁首/頁尾 | 語言 |
| 等待延遲 | 低 |
| PDF/A 轉換 | 低 |
範式轉移
Gotenberg 遷移的根本轉變在於從使用 multipart 表單資料的 HTTP API 呼叫轉變為原生 C# 方法呼叫:
高登堡: HTTP POST multipart/form-data 至 Docker 容器
IronPDF: C# 物件上的直接方法呼叫
開始之前
先決條件
- .NET 版本:IronPDF支援 .NET Framework 4.6.2+ 和 .NET Core 3.1+ / .NET 5/6/7/8/9+ 2.許可證密鑰:請從ironpdf.com取得您的IronPDF許可證密鑰。 3.規劃基礎設施移除:記錄哥登堡容器在遷移後的退役事宜
辨識所有高登堡使用方式
# Find direct HTTP calls to Gotenberg
grep -r "gotenberg\|/forms/chromium\|/forms/libreoffice\|/forms/pdfengines" --include="*.cs" .
# Find GotenbergSharpApiClient usage
grep -r "GotenbergSharpClient\|Gotenberg.Sharp\|ChromiumRequest" --include="*.cs" .
# Find Docker/Kubernetes高登堡configuration
grep -r "gotenberg/gotenberg\|gotenberg:" --include="*.yml" --include="*.yaml" .
# Find direct HTTP calls to Gotenberg
grep -r "gotenberg\|/forms/chromium\|/forms/libreoffice\|/forms/pdfengines" --include="*.cs" .
# Find GotenbergSharpApiClient usage
grep -r "GotenbergSharpClient\|Gotenberg.Sharp\|ChromiumRequest" --include="*.cs" .
# Find Docker/Kubernetes高登堡configuration
grep -r "gotenberg/gotenberg\|gotenberg:" --include="*.yml" --include="*.yaml" .
NuGet 套件變更
# Remove高登堡client (if using)
dotnet remove package Gotenberg.Sharp.API.Client
# Install IronPDF
dotnet add package IronPdf
# Remove高登堡client (if using)
dotnet remove package Gotenberg.Sharp.API.Client
# Install IronPDF
dotnet add package IronPdf
快速啟動遷移
步驟 1:更新授權組態
之前 (高登堡):。
Gotenberg 不需要授權,但需要具備容器 URL 的 Docker 基礎架構。
private readonly string _gotenbergUrl = "http://localhost:3000";
private readonly string _gotenbergUrl = "http://localhost:3000";
Private ReadOnly _gotenbergUrl As String = "http://localhost:3000"
After (IronPDF):
// Set once at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY";
// Set once at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY";
' Set once at application startup
IronPdf.License.LicenseKey = "YOUR-IRONPDF-LICENSE-KEY"
步驟 2:更新命名空間匯入
// Before (Gotenberg)
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
// After (IronPDF)
using IronPdf;
using IronPdf.Rendering;
// Before (Gotenberg)
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
// After (IronPDF)
using IronPdf;
using IronPdf.Rendering;
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.IO
Imports IronPdf
Imports IronPdf.Rendering
完整的 API 參考資料
高登堡Endpoint 到IronPDF的映射
| 哥登堡路線 | IronPDF 同等級產品 |
|---|---|
POST /forms/chromium/convert/html |
ChromePdfRenderer.RenderHtmlAsPdf() |
POST /forms/chromium/convert/url |
ChromePdfRenderer.RenderUrlAsPdf() |
POST /forms/pdfengines/merge |
PdfDocument.Merge() |
POST /forms/pdfengines/convert |
pdf.SaveAs() 帶設置 |
GET /health |
不適用 |
表單參數至 RenderingOptions 對應
| 高登堡參數 | IronPDF 特性 | 轉換注意事項 |
|---|---|---|
paperWidth(英吋) |
RenderingOptions.PaperSize |
使用枚舉或自訂大小 |
paperHeight(英吋) |
RenderingOptions.PaperSize |
使用枚舉或自訂大小 |
marginTop(英吋) |
RenderingOptions.MarginTop |
毫米數乘以 25.4 |
marginBottom(英吋) |
RenderingOptions.MarginBottom |
毫米數乘以 25.4 |
printBackground |
RenderingOptions.PrintHtmlBackgrounds |
布林 |
landscape |
RenderingOptions.PaperOrientation |
Landscape枚舉 |
waitDelay |
RenderingOptions.RenderDelay |
轉換為毫秒 |
程式碼遷移範例
範例 1:基本 HTML 到 PDF
之前 (高登堡):。
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergExample
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
var html = "<html><body><h1>Hello from Gotenberg</h1></body></html>";
content.Add(new StringContent(html), "files", "index.html");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("output.pdf", pdfBytes);
Console.WriteLine("PDF generated successfully");
}
}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergExample
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
var html = "<html><body><h1>Hello from Gotenberg</h1></body></html>";
content.Add(new StringContent(html), "files", "index.html");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("output.pdf", pdfBytes);
Console.WriteLine("PDF generated successfully");
}
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.IO
Module GotenbergExample
Async Function Main() As Task
Dim gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html"
Using client As New HttpClient()
Using content As New MultipartFormDataContent()
Dim html = "<html><body><h1>Hello from Gotenberg</h1></body></html>"
content.Add(New StringContent(html), "files", "index.html")
Dim response = Await client.PostAsync(gotenbergUrl, content)
Dim pdfBytes = Await response.Content.ReadAsByteArrayAsync()
Await File.WriteAllBytesAsync("output.pdf", pdfBytes)
Console.WriteLine("PDF generated successfully")
End Using
End Using
End Function
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class IronPdfExample
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var html = "<html><body><h1>Hello from IronPDF</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF generated successfully");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class IronPdfExample
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var html = "<html><body><h1>Hello from IronPDF</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
Console.WriteLine("PDF generated successfully");
}
}
Imports System
Imports IronPdf
Class IronPdfExample
Shared Sub Main()
Dim renderer = New ChromePdfRenderer()
Dim html = "<html><body><h1>Hello from IronPDF</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
Console.WriteLine("PDF generated successfully")
End Sub
End Class
差異很大:Gotenberg 需要建構一個 HttpClient,建置 MultipartFormDataContent,向正在執行的 Docker 容器發出非同步 HTTP POST 請求,並處理位元組陣列回應。IronPDF將其簡化為三行程式碼,透過 ChromePdfRenderer 方法呼叫-沒有網路開銷,沒有容器依賴,沒有非同步複雜性。 請參閱 HTML to PDF 文件,以瞭解其他渲染選項。
範例 2:URL 到 PDF 的轉換
之前 (高登堡):。
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergUrlToPdf
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/url";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
content.Add(new StringContent("https://example.com"), "url");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("webpage.pdf", pdfBytes);
Console.WriteLine("PDF from URL generated successfully");
}
}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergUrlToPdf
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/url";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
content.Add(new StringContent("https://example.com"), "url");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("webpage.pdf", pdfBytes);
Console.WriteLine("PDF from URL generated successfully");
}
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.IO
Module GotenbergUrlToPdf
Async Function Main() As Task
Dim gotenbergUrl As String = "http://localhost:3000/forms/chromium/convert/url"
Using client As New HttpClient()
Using content As New MultipartFormDataContent()
content.Add(New StringContent("https://example.com"), "url")
Dim response As HttpResponseMessage = Await client.PostAsync(gotenbergUrl, content)
Dim pdfBytes As Byte() = Await response.Content.ReadAsByteArrayAsync()
Await File.WriteAllBytesAsync("webpage.pdf", pdfBytes)
Console.WriteLine("PDF from URL generated successfully")
End Using
End Using
End Function
End Module
After (IronPDF):
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class IronPdfUrlToPdf
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
Console.WriteLine("PDF from URL generated successfully");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
class IronPdfUrlToPdf
{
static void Main()
{
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderUrlAsPdf("https://example.com");
pdf.SaveAs("webpage.pdf");
Console.WriteLine("PDF from URL generated successfully");
}
}
Imports System
Imports IronPdf
Class IronPdfUrlToPdf
Shared Sub Main()
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderUrlAsPdf("https://example.com")
pdf.SaveAs("webpage.pdf")
Console.WriteLine("PDF from URL generated successfully")
End Sub
End Class
Gotenberg 方法需要不同的端點(/forms/chromium/convert/url),使用 URL 作為表單欄位建立多部分內容,並處理非同步 HTTP 回應。IronPDF的 RenderUrlAsPdf() 方法直接接受 URL,並同步傳回一個 PdfDocument 物件。 進一步瞭解 URL 至 PDF 轉換。
範例 3:自訂紙張大小和邊界
之前 (高登堡):。
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergCustomSize
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
var html = "<html><body><h1>Custom Size PDF</h1></body></html>";
content.Add(new StringContent(html), "files", "index.html");
content.Add(new StringContent("8.5"), "paperWidth");
content.Add(new StringContent("11"), "paperHeight");
content.Add(new StringContent("0.5"), "marginTop");
content.Add(new StringContent("0.5"), "marginBottom");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("custom-size.pdf", pdfBytes);
Console.WriteLine("Custom size PDF generated successfully");
}
}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.IO;
class GotenbergCustomSize
{
static async Task Main()
{
var gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html";
using var client = new HttpClient();
using var content = new MultipartFormDataContent();
var html = "<html><body><h1>Custom Size PDF</h1></body></html>";
content.Add(new StringContent(html), "files", "index.html");
content.Add(new StringContent("8.5"), "paperWidth");
content.Add(new StringContent("11"), "paperHeight");
content.Add(new StringContent("0.5"), "marginTop");
content.Add(new StringContent("0.5"), "marginBottom");
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("custom-size.pdf", pdfBytes);
Console.WriteLine("Custom size PDF generated successfully");
}
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
Imports System.IO
Class GotenbergCustomSize
Shared Async Function Main() As Task
Dim gotenbergUrl = "http://localhost:3000/forms/chromium/convert/html"
Using client As New HttpClient()
Using content As New MultipartFormDataContent()
Dim html = "<html><body><h1>Custom Size PDF</h1></body></html>"
content.Add(New StringContent(html), "files", "index.html")
content.Add(New StringContent("8.5"), "paperWidth")
content.Add(New StringContent("11"), "paperHeight")
content.Add(New StringContent("0.5"), "marginTop")
content.Add(New StringContent("0.5"), "marginBottom")
Dim response = Await client.PostAsync(gotenbergUrl, content)
Dim pdfBytes = Await response.Content.ReadAsByteArrayAsync()
Await File.WriteAllBytesAsync("custom-size.pdf", pdfBytes)
Console.WriteLine("Custom size PDF generated successfully")
End Using
End Using
End Function
End Class
After (IronPDF):
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
using IronPdf.Rendering;
class IronPdfCustomSize
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 50;
renderer.RenderingOptions.MarginBottom = 50;
var html = "<html><body><h1>Custom Size PDF</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom-size.pdf");
Console.WriteLine("Custom size PDF generated successfully");
}
}
// NuGet: Install-Package IronPdf
using System;
using IronPdf;
using IronPdf.Rendering;
class IronPdfCustomSize
{
static void Main()
{
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter;
renderer.RenderingOptions.MarginTop = 50;
renderer.RenderingOptions.MarginBottom = 50;
var html = "<html><body><h1>Custom Size PDF</h1></body></html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("custom-size.pdf");
Console.WriteLine("Custom size PDF generated successfully");
}
}
Imports System
Imports IronPdf
Imports IronPdf.Rendering
Module IronPdfCustomSize
Sub Main()
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.PaperSize = PdfPaperSize.Letter
renderer.RenderingOptions.MarginTop = 50
renderer.RenderingOptions.MarginBottom = 50
Dim html As String = "<html><body><h1>Custom Size PDF</h1></body></html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("custom-size.pdf")
Console.WriteLine("Custom size PDF generated successfully")
End Sub
End Module
Gotenberg 要求將基於字串的參數("8.5"、"11"、"0.5")新增至 multipart 表單資料中-沒有型別安全,沒有 IntelliSense,容易輸入錯誤。IronPDF提供具有枚舉和數值邊距值的強類型屬性。 請注意,IronPDF 的頁邊空白以毫米為單位 (50mm ≈ 2 英寸),而高登堡使用英寸。
關鍵遷移注意事項
單位轉換
此次高登堡轉移中最重要的轉換是邊際單位:
// Gotenberg: margins in inches
content.Add(new StringContent("0.5"), "marginTop"); // 0.5 inches
content.Add(new StringContent("1"), "marginBottom"); // 1 inch
// IronPDF: margins in millimeters
renderer.RenderingOptions.MarginTop = 12.7; // 0.5 inches × 25.4 = 12.7mm
renderer.RenderingOptions.MarginBottom = 25.4; // 1 inch × 25.4 = 25.4mm
// Gotenberg: margins in inches
content.Add(new StringContent("0.5"), "marginTop"); // 0.5 inches
content.Add(new StringContent("1"), "marginBottom"); // 1 inch
// IronPDF: margins in millimeters
renderer.RenderingOptions.MarginTop = 12.7; // 0.5 inches × 25.4 = 12.7mm
renderer.RenderingOptions.MarginBottom = 25.4; // 1 inch × 25.4 = 25.4mm
' Gotenberg: margins in inches
content.Add(New StringContent("0.5"), "marginTop") ' 0.5 inches
content.Add(New StringContent("1"), "marginBottom") ' 1 inch
' IronPDF: margins in millimeters
renderer.RenderingOptions.MarginTop = 12.7 ' 0.5 inches × 25.4 = 12.7mm
renderer.RenderingOptions.MarginBottom = 25.4 ' 1 inch × 25.4 = 25.4mm
轉換公式: millimeters = inches × 25.4
同步與非同步
由於 HTTP 通訊的關係,Gotenberg 需要進行同步操作:
// Gotenberg: Forced async due to network calls
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
// IronPDF: Synchronous in-process execution
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// IronPDF: Async wrapper if needed
var pdf = await Task.Run(() => renderer.RenderHtmlAsPdf(html));
// Gotenberg: Forced async due to network calls
var response = await client.PostAsync(gotenbergUrl, content);
var pdfBytes = await response.Content.ReadAsByteArrayAsync();
// IronPDF: Synchronous in-process execution
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("output.pdf");
// IronPDF: Async wrapper if needed
var pdf = await Task.Run(() => renderer.RenderHtmlAsPdf(html));
Imports System.Net.Http
' Gotenberg: Forced async due to network calls
Dim response = Await client.PostAsync(gotenbergUrl, content)
Dim pdfBytes = Await response.Content.ReadAsByteArrayAsync()
' IronPDF: Synchronous in-process execution
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("output.pdf")
' IronPDF: Async wrapper if needed
Dim pdf = Await Task.Run(Function() renderer.RenderHtmlAsPdf(html))
錯誤處理
// Gotenberg: HTTP error handling
try
{
var response = await client.PostAsync(gotenbergUrl, content);
response.EnsureSuccessStatusCode(); // What if 500? 503? Timeout?
}
catch (HttpRequestException ex) { /* Network error */ }
catch (TaskCanceledException ex) { /* Timeout */ }
// IronPDF: Standard .NET exceptions
try
{
var pdf = renderer.RenderHtmlAsPdf(html);
}
catch (Exception ex)
{
Console.WriteLine($"PDF generation failed: {ex.Message}");
}
// Gotenberg: HTTP error handling
try
{
var response = await client.PostAsync(gotenbergUrl, content);
response.EnsureSuccessStatusCode(); // What if 500? 503? Timeout?
}
catch (HttpRequestException ex) { /* Network error */ }
catch (TaskCanceledException ex) { /* Timeout */ }
// IronPDF: Standard .NET exceptions
try
{
var pdf = renderer.RenderHtmlAsPdf(html);
}
catch (Exception ex)
{
Console.WriteLine($"PDF generation failed: {ex.Message}");
}
Imports System
Imports System.Net.Http
Imports System.Threading.Tasks
' Gotenberg: HTTP error handling
Try
Dim response = Await client.PostAsync(gotenbergUrl, content)
response.EnsureSuccessStatusCode() ' What if 500? 503? Timeout?
Catch ex As HttpRequestException
' Network error
Catch ex As TaskCanceledException
' Timeout
End Try
' IronPDF: Standard .NET exceptions
Try
Dim pdf = renderer.RenderHtmlAsPdf(html)
Catch ex As Exception
Console.WriteLine($"PDF generation failed: {ex.Message}")
End Try
基礎架構移除
遷移後,請從您的基礎架構中移除 Gotenberg:
# REMOVE from docker-compose.yml:
# services:
# gotenberg:
# image: gotenberg/gotenberg:8
# ports:
# - "3000:3000"
# deploy:
# resources:
# limits:
# memory: 2G
# REMOVE from docker-compose.yml:
# services:
# gotenberg:
# image: gotenberg/gotenberg:8
# ports:
# - "3000:3000"
# deploy:
# resources:
# limits:
# memory: 2G
效能考量
延遲比較
| 手術 | 高登堡 (溫暖) | 高登堡(冷啟動) | IronPDF (首次渲染) | IronPDF (後續) |
|---|---|---|---|---|
| 簡單的 HTML | 150-300 毫秒 | 2-5 秒 | 1-2 秒 | 50-150ms |
| 複雜的 HTML | 500-1500ms | 3-7 秒 | 1.5-3 秒 | 200-800ms |
| URL 渲染 | 1-5 秒 | 3-10 秒 | 1-5 秒 | 500ms-3s |
消除基礎結構成本
| 資源 | 高登堡 | IronPDF |
|---|---|---|
| 所需的容器 | 1-N (縮放) | 0 |
| 每個容器的記憶體 | 512MB-2GB | 不適用 |
| 每次請求的網路開銷 | 10-100 毫秒 | 0ms |
| 健康檢查端點 | 要求 | 不需要 |
| 負載平衡器 | 經常需要 | 不需要 |
疑難排解
問題 1:不需要 HttpClient 模式
問題:代碼仍然使用 HttpClient 和 MultipartFormDataContent。
解:完全替換為 ChromePdfRenderer:
// Remove all of this:
// using var client = new HttpClient();
// using var content = new MultipartFormDataContent();
// content.Add(new StringContent(html), "files", "index.html");
// var response = await client.PostAsync(url, content);
// Replace with:
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Remove all of this:
// using var client = new HttpClient();
// using var content = new MultipartFormDataContent();
// content.Add(new StringContent(html), "files", "index.html");
// var response = await client.PostAsync(url, content);
// Replace with:
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
問題 2:邊際單位錯誤
問題:遷移後 PDF 檔案的邊距不正確。
解決方法:將英吋轉換為毫米:
//高登堡used inches: "0.5"
//IronPDFuses millimeters: 0.5 × 25.4 = 12.7
renderer.RenderingOptions.MarginTop = 12.7;
//高登堡used inches: "0.5"
//IronPDFuses millimeters: 0.5 × 25.4 = 12.7
renderer.RenderingOptions.MarginTop = 12.7;
問題 3:容器 URL 參考資料
問題:代碼包含 http://gotenberg:3000 或類似 URL。
解決方案:移除所有容器 URL 引用-IronPDF 以進程內方式執行:
// Remove:
// private readonly string _gotenbergUrl = "http://gotenberg:3000";
//IronPDFneeds no URL - it's in-process
var renderer = new ChromePdfRenderer();
// Remove:
// private readonly string _gotenbergUrl = "http://gotenberg:3000";
//IronPDFneeds no URL - it's in-process
var renderer = new ChromePdfRenderer();
遷移清單
預遷移
- 清點程式碼庫中所有高登堡HTTP 調用
- 記錄目前高登堡配置(逾時、頁邊距、紙張尺寸)
- 識別所有 Docker/Kubernetes高登堡配置
- 取得IronPDF許可證密鑰
- 規劃基礎建設退役
程式碼遷移
- 安裝 IronPdf NuGet 套件:
dotnet add package IronPdf - 移除高登堡用戶端軟體包
- 將所有對高登堡的 HTTP 呼叫替換為IronPDF方法調用
- 將邊距單位從英吋轉換為毫米
- 更新錯誤處理(HTTP 錯誤 → .NET 異常)
- 新增啟動時許可證金鑰初始化功能
基礎架構遷移
- 從 Docker Compose/Kubernetes 移除 Gotenberg
- 更新 CI/CD 管線(移除高登堡鏡像拉取)
- 移除哥德堡健康檢查
- 從設定中移除高登堡URL
測試
- 測試 HTML 至 PDF 的轉換
- 測試 URL 至 PDF 的轉換
- 核實邊距和尺寸準確性
- 負載下的效能測試
- 測試首次渲染預熱時間
後遷移
- 移除高登堡容器部署
- 歸檔高登堡設定檔
- 更新文件
- 監控應用程式記憶體使用情況
- 檢查是否有孤立的網路連接

