Gotenberg與IronPDF:技術比較指南
當.NET開發者評估PDF生成解決方案時,Gotenberg作為一種基於Docker的微服務通過REST API調用將HTML轉換為PDF而突出。 雖然適用於多樣的架構,但Gotenberg引入了顯著的基礎設施開銷——Docker容器、網路延遲和操作複雜性。 IronPDF提供了一個替代方案:一個內嵌的NuGet包,提供相同的基於Chromium的渲染,無需容器、網路調用或基礎設施管理。
此比較檢視兩種解決方案在技術相關維度上的表現,以協助專業的開發者和架構師在.NET PDF需求上做出明智選擇。
了解Gotenberg
Gotenberg是一種基於Docker的PDF生成微服務架構。 它作為獨立容器運行,公開REST API端點,以將HTML、URL和其他格式轉換為PDF。 每個PDF操作都需要HTTP調用到Gotenberg服務。
Gotenberg使用像POST /forms/chromium/convert/html 用於HTML到PDF的端點,POST /forms/chromium/convert/url 用於URL到PDF的轉換。 配置是通過multipart/form-data傳遞的,帶有如paperWidth, paperHeight, marginTop, 和marginBottom(以英吋為單位)的字串參數。 該服務需要Docker部署、容器編排(Kubernetes/Docker Compose)和網路基礎設施。
架構要求:
- Docker容器的部署和管理
- 每個PDF請求的網路通信(容器HTTP往返)
- 容器冷啟動處理(首次請求的初始化延遲)
- 健康檢查端點和服務監控
- 每個請求的multipart/form-data構建
瞭解IronPDF
IronPDF是一個本地的.NET程式庫,以NuGet包形式內嵌運行。 它提供基於Chromium的HTML渲染,無需外部服務、網路調用或容器基礎設施。
IronPDF使用ChromePdfRenderer 作為其主要渲染類別,帶有方法如RenderHtmlAsPdf() 和RenderUrlAsPdf()。 配置使用在PaperSize, MarginTop, MarginBottom(以毫米為單位)。 文件可以使用BinaryData存取。
該程式庫僅需要:
- NuGet包安裝(
dotnet add package IronPdf) - 授權金鑰配置
- 標準.NET專案設置
架構與基礎設施比較
這些解決方案之間的基本差異在於其部署和運行時架構。
| 因數 | Gotenberg | IronPDF |
|---|---|---|
| 部署 | Docker容器 + 編排 | 單一NuGet套件 |
| 架構 | 微服務(REST API) | 內嵌程式庫 |
| 每個請求的延遲 | 容器HTTP往返 | 內嵌(開銷最小化) |
| 冷啟動 | 容器初始化延遲 | 引擎初始化(僅首次渲染) |
| 基礎設施 | Docker, Kubernetes, 負載平衡器 | 無需 |
| 網路依賴性 | 需要 | None |
| 故障模式 | 網路、容器、服務故障 | 標準.NET例外 |
| API風格 | REST multipart/form-data | 本地C#方法調用 |
| 擴展性 | 水平擴展(更多容器) | 垂直擴展(內嵌) |
| 調試 | 分佈式追蹤 | 標準調試器 |
| 記憶體管理 | 獨立容器分配 | 共享應用記憶體 |
| 版本控制 | 容器映像標籤 | NuGet包版本 |
| 健康檢查 | 需求HTTP端點 | 不需要(內嵌) |
| CI/CD複雜度 | 容器構建,註冊表推送 | 標準.NET構建 |
Gotenberg的基於Docker的方法要求容器部署、健康監控和網路基礎設施管理。 IronPDF通過內嵌運行完全消除了這一基礎設施層。
程式碼比較:常見的PDF操作
基本 HTML 到 PDF 轉換
最基本的操作明顯展示了架構上的差異。
Gotenberg:
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 ModuleIronPDF:
// 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該服務要求創建一個index.html)添加,進行異步HTTP POST到端點,讀取響應字節,並寫入磁碟。 每個請求都通過網路進行,並伴隨相關的延遲和故障模式。
IronPDF創建一個SaveAs()保存。 該操作是同步的、內嵌的,使用型別化方法而不是基於字串的表單數據。
有關進階HTML渲染選項,請查看HTML到PDF轉換指南。
URL到PDF轉換
將即時網頁轉換為PDF顯示了類似的架構模式。
Gotenberg:
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 ModuleIronPDF:
// 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容器使用/forms/chromium/convert/url端點,URL作為表單數據傳遞。 IronPDF直接使用URL字串呼叫RenderUrlAsPdf()——單一方法呼叫,取代了HTTP基礎設施。
自定義頁面大小和邊距
配置處理顯示出API設計的差異。
Gotenberg:
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 ClassIronPDF:
// 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該方法使用字串參數("8.5", "11", "0.5")添加到multipart表單數據中。 紙張尺寸以英吋為單位。 每個參數皆是獨立的Add()調用,沒有型別檢查或IntelliSense支持。
IronPDF使用RenderingOptions上的型別化屬性。 PdfPaperSize.Letter),邊距為以毫米為單位的數值。 型別化API提供編譯時檢查和IDE支持。
在IronPDF教程中了解更多有關渲染配置的資訊。
API映射參考
對於評估Gotenberg遷移或比較功能的開發者,此映射顯示了等效操作:
端點到方法的映射
| Gotenberg路由 | IronPDF等效 |
|---|---|
POST /forms/chromium/convert/html | ChromePdfRenderer.RenderHtmlAsPdf() |
POST /forms/chromium/convert/url | ChromePdfRenderer.RenderUrlAsPdf() |
POST /forms/chromium/convert/markdown | 首先將Markdown渲染為HTML |
POST /forms/pdfengines/merge | PdfDocument.Merge() |
POST /forms/pdfengines/metadata/read | pdf.MetaData |
POST /forms/pdfengines/metadata/write | pdf.MetaData.Author = "..." |
GET /health | 不適用 |
表單參數到RenderingOptions的映射
| Gotenberg參數 | IronPDF屬性 | 轉換注意事項 |
|---|---|---|
paperWidth(英吋) | RenderingOptions.SetCustomPaperSizeInInches() | 使用方法自定義 |
paperHeight(英吋) | RenderingOptions.SetCustomPaperSizeInInches() | 使用方法自定義 |
marginTop(英吋) | RenderingOptions.MarginTop | 乘以25.4換算成毫米 |
marginBottom(英吋) | RenderingOptions.MarginBottom | 乘以25.4換算成毫米 |
marginLeft(英吋) | RenderingOptions.MarginLeft | 乘以25.4換算成毫米 |
marginRight(英吋) | RenderingOptions.MarginRight | 乘以25.4換算成毫米 |
printBackground | RenderingOptions.PrintHtmlBackgrounds | 布林值 |
landscape | RenderingOptions.PaperOrientation | Landscape枚舉 |
scale | RenderingOptions.Zoom | 百分比(100 = 1.0) |
waitDelay | RenderingOptions.RenderDelay | 轉換為毫秒 |
emulatedMediaType | RenderingOptions.CssMediaType | Screen 或 Print |
注意單位轉換:Gotenberg使用英吋作為邊距(例如,"0.5" = 0.5英吋 = 12.7毫米),而IronPDF使用毫米。
基礎設施比較
GotenbergDocker Compose
Gotenberg需要容器基礎設施:
#Gotenbergrequires container management
version: '3.8'
services:
app:
depends_on:
- gotenberg
environment:
- GOTENBERG_URL=http://gotenberg:3000
gotenberg:
image: gotenberg/gotenberg:8
ports:
- "3000:3000"
deploy:
resources:
limits:
memory: 2G
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s#Gotenbergrequires container management
version: '3.8'
services:
app:
depends_on:
- gotenberg
environment:
- GOTENBERG_URL=http://gotenberg:3000
gotenberg:
image: gotenberg/gotenberg:8
ports:
- "3000:3000"
deploy:
resources:
limits:
memory: 2G
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30sIronPDF配置
IronPDF不需要額外服務:
#IronPDF- No additional services needed
version: '3.8'
services:
app:
environment:
- IRONPDF_LICENSE_KEY=${IRONPDF_LICENSE_KEY}
# NoGotenbergservice. No health checks. No resource limits.#IronPDF- No additional services needed
version: '3.8'
services:
app:
environment:
- IRONPDF_LICENSE_KEY=${IRONPDF_LICENSE_KEY}
# NoGotenbergservice. No health checks. No resource limits.基礎設施的差異很大:Gotenberg需要容器部署、健康監控、資源分配和服務依賴。 IronPDF與應用程序一起運行內嵌。
性能特徵
| 因數 | Gotenberg | IronPDF |
|---|---|---|
| 處理 | 每個請求的容器HTTP往返 | 內嵌(無網路開銷) |
| 啟動 | 每次部署/擴展事件的容器初始化 | 每個應用程式生命週期內引擎初始化一次 |
| 記憶體 | 獨立容器分配 | 共享應用記憶體 |
| 後續渲染 | 每次請求的網路開銷仍然存在 | 初始化後的開銷最小 |
Gotenberg的架構在每次請求中增加了網路往返的開銷,在每次部署或擴展事件中出現容器冷啟動。 IronPDF的首次渲染會生成引擎初始化,但後續渲染以內嵌方式運行,開銷最小。
當團隊考慮從Gotenberg轉到IronPDF
開發團隊評估從Gotenberg轉向IronPDF有多種原因:
基礎設施開銷: 服務需要Docker、容器編排(Kubernetes/Docker Compose)、服務發現和負載平衡。 尋求更簡單部署的團隊發現IronPDF的NuGet only方法消除了這些基礎設施的擔憂。
網路延遲: 透過容器的每個PDF操作都需要對獨立服務的HTTP調用,為每個請求增加了網路往返開銷。對於高流量應用程式,這種開銷會累積。 IronPDF的內嵌方法在初始化後幾乎沒有開銷。
冷啟動問題: 容器啟動使首次請求增加了初始化延遲。 即使是暖容器亦有網路開銷。 每次Pod重啟、擴展升級或部署都會觸發冷啟動。 IronPDF的初始化僅發生在每個應用程式生命週期內的一次。
操作複雜性:需要單獨管理容器的健康狀況、擴展、日誌和監控。 網路超時、服務不可用和容器當機成為應用程式的擔憂。 IronPDF使用標準.NET異常處理。
Multipart Form Data API: 服務的每個請求都需要構建帶有基於字串參數的multipart/form-data負載——冗長且沒有編譯時型別檢查。 IronPDF提供型別化的C#屬性,具備IntelliSense支持。
版本管理: 其容器映像分別於您的應用更新。 API變化可能會中斷集成。 IronPDF版本通過NuGet進行管理,這是一個標準的.NET依賴管理。
優勢和考量
Gotenberg優勢
- 多語言架構:適用於任何可以進行HTTP調用的語言
- 語言無關性:未綁定於.NET生態系統
- MIT許可證:免費且開源
- 微服務模式:適合容器化架構
Gotenberg考慮因素
- 基礎設施開銷:需要Docker、Kubernetes、負載平衡器
- 網路延遲:每個請求的容器HTTP往返
- 冷啟動:容器初始化延遲
- 基於字串的API:無型別安全或IntelliSense
- 分佈式調試:需要分佈式追蹤
- 健康監控:需要額外的端點來管理
IronPDF的優勢
IronPDF的考量
- .NET專用:設計用於.NET生態系統
- 商業授權:生產使用需要商業授權
Gotenberg和IronPDF在.NET應用程序的PDF生成中代表了根本不同的途徑。 Gotenberg基於Docker的微服務架構引入了容器管理、網路延遲和操作複雜性。 每一PDF操作都要求HTTP通信,並伴有相應的故障模式和冷啟動懲罰。
IronPDF提供相同的基於Chromium的渲染作為一個內嵌程式庫。 NuGet包消除了Docker容器、網路呼叫和基礎設施管理。 型別化C# API取代了基於字串的multipart表單數據。 標準.NET例外處理取代了HTTP狀態代碼和網路故障模式。
隨著組織計劃.NET 10、C# 14和至2026年的應用程式開發,在微服務基礎設施開銷和內嵌程式庫簡單性之間的選擇顯著影響部署和操作複雜度。 尋求減少基礎設施負擔,同時保持HTML/CSS/JavaScript渲染保真度的團隊會發現IronPDF有效地滿足這些要求。
開始評估IronPDF,通過免費試用,並查看更多詳細文檔,來評估其對您的具體需求是否合適。
