C#'ta HTML'den PDF'e - Kütüphane Seçeneklerinin Gerçekliği
C#'da HTML'yi PDF'ye dönüştürmek, aslında HTML'yi render'layan bir kütüphane gerektirir — etiketler alt kümesinin bir ayrıştırıcısı ve CSS 2.1'i tahmin edeni değil. Stack Overflow başlıklarında ve Reddit tartışmalarında önerilen çoğu kütüphane ya modern CSS'yi render'layamaz, ticari kullanım için diskalifiye eden lisans kısıtlamaları taşır veya düzeltilmemiş güvenlik açığıyle terk edilmiş durumdadır.
Bu makale, geliştiricilerin 'HTML to PDF C#' aradıklarında karşıladıkları kütüphaneleri karşılaştırır, her birinin neyi renderlayabileceğini ve render'layamayacağını belgelendirir, metodoloji ile performans kriterleri içerisindedir ve her yaklaşımın gerçek operasyonel maliyetini gösterir.
Quickstart: HTML'den PDF'ye in C
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>");
pdf.SaveAs("output.pdf");
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>");
pdf.SaveAs("output.pdf");
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>")
pdf.SaveAs("output.pdf")
NuGet üzerinden yükleyin: Install-Package IronPdf. Ek bağımlılıklar olmadan Windows, Linux, macOS ve Docker'a dağıtılır.
HTML'den PDF'ye Dönüşüm Neden Zor?
HTML'i doğru şekilde PDF'ye renderlemek, bir web tarayıcısının kullandığı beş bileşeni aynı şekilde uygulamayı gerektirir: bir HTML ayrıştırıcı, bir CSS motoru (Flexbox, Grid, kaskad, özgüllük ve medya sorguları dahil), bir JavaScript çalışma zamanı, bir düzen motoru ve bunu PDF'ye alta piksellik hassasiyette birleştiren bir render hattı.
Geleneksel PDF kütüphaneleri ilk iki bileşeni kısmen uygular ve JavaScript'i tamamen geçer. Bu nedenle basit HTML ile başa çıkabilirler ancak modern bir tarayıcının doğru render'layacağı her şeyde kırılırlar. Tarayıcı çıktısını eşleştirmenin tek yolu bir tarayıcı motoru kullanmaktır.
Hangi Kütüphaneler Gerçekten HTML'yi PDF'ye Dönüştürür?
wkhtmltopdfSarmalayıcıları — DLL Yükleme Hatası Ekosistemi
Bu makalelere geliştiricileri getiren en yaygın arama sorgusu, şu varyasyonlardan biridir:
System.DllNotFoundException: 'libwkhtmltox' DLL'i yüklenemedi
Platforma özgü varyantlar şunlardır:
'wkhtmltox' veya bağımlılıklarından birini yükleme başarısız
(Linux — libwkhtmltox.so not found)
Belirtilen modül bulunamadı. (0x8007007E)
(Windows — wkhtmltox.dll path not configured)
dyld: Kütüphane yüklenemedi: libwkhtmltox.dylib
(macOS — not supported on ARM64/Apple Silicon)
Bu hatalar DinkToPdf, NReco.PdfGenerator, WkHtmlToXSharp ve aynı terkedilmiş ikili etrafındaki diğer C# sarmalayıcılarından gelmektedir. wkhtmltopdf GitHub organizasyonu Temmuz 2024'te arşivlendi. Altında yatan QtWebKit motoru Qt tarafından 2015'te kaldırıldı. proje durum sayfası bunu açıkça kullanım dışı olarak işaretliyor.
DLL yükleme sorunlarının ötesinde, render motoru yaklaşık olarak Safari 2011 kapasitesinde donmuş durumda. Flexbox yok, Grid yok, sınırlı CSS3, güvensiz JavaScript. Ve yamalı olmayan kritik zafiyetler var: ⟨a href="https://github.com/wkhtmltopdf/wkhtmltopdf/issues/5249"⟩CVE-2022-35583⟨/a⟩ (CVSS 9.8), özel olarak oluşturulmuş HTML aracılığıyla AWS kimlik bilgilerini dışa sızdırabilen SSRF saldırılarına olanak tanır.
wkhtmltopdf'nin zamanı geçti. DLL yükleme hataları daha derin bir sorunun belirtisidir: ileriye yönelik hiçbir yolu olmayan terk edilmiş bir yazılıma bağımlısınız.
iText(pdfHTML Eklentisi) — Sınırlı CSS, AGPL Lisanslı
iText'in pdfHTML modülü, HTML'yi özel bir ayrıştırıcı kullanarak PDF'ye dönüştürür — bir tarayıcı motoru değil. Temel HTML/CSS kodlarını işler ancak Flexbox, Grid veya JavaScript'i render etmez.
Hata modu sessizdir: pdfHTML, desteklenmeyen CSS ile karşılaştığında istisnalar fırlatmaz. Yapabildiklerini işler ve geri kalanını yoksayar. display: flex, gap: 20px ve justify-content: space-between ile bir konteyner, arada boşluk olmadan dikey istiflenmiş elemanlar olarak işler. Geliştiriciler bunu entegrasyon sonrasında keşfeder, değilken.
Lisanslama: AGPL — tüm ağ erişim uygulanabilir uygulamanızı açık kaynak haline getirmenizi veya ticari lisans satın almanızı gerektirir. Fiyatlandırma yayınlanmamıştır; üçüncü parti veriler yıllık 15.000–210.000 dolar arasını gösterir.
Bellek Kullanımı Nasıl Karşılaştırılır?
iText'in pdfHTML, işlemler için tüm belgeyi belleğe yükler. Tipik iş belgeleri için bu yönetilebilir ancak gömülü resimlerle büyük HTML raporları, yayınlama yaklaşımlarıyla karşılaştırıldığında önemli bellek baskısına neden olabilir.
NedenPDFSharpHTML Desteklemez?
PdfSharp "HTML to PDF" arama sonuçlarında popülerliği (34,9 milyon NuGet indirme) ve sıkça önerilmesi nedeniyle görünür. Ancak PdfSharp'nin bir HTML ayrıştırıcısı yok. Koordinat tabanlı bir çizim API'si sağlar: açık X/Y pozisyonları ile DrawString(), DrawRectangle(), DrawImage().
Sık önerilen geçici çözüm, HtmlRenderer.PdfSharp, yalnızca HTML 4.01 ve CSS Seviye 2'yi destekler. HTML'iniz 2010 sonrasında tanıtılan bir CSS özelliği kullanıyorsa — Flexbox (2012), Grid (2017), özel özellikler (2017), border-radius (2011) — işlenmeyecektir.
PdfSharp'yi seçen ve HTML desteği bekleyen geliştiriciler, ya her elemanı koordinat tabanlı kodla elle konumlandırır ya da HTML işleme için ikinci bir kütüphane ekler — bu noktada PdfSharp gereksiz olur.
Puppeteer SharpNeden Kaynak Yoğun?
Puppeteer Sharp, Başsız Chrome'u .NET bağlamaları aracılığıyla kontrol eder. Render doğruluğu Chrome ile eşleşmektedir çünkü Chrome'dur. Maliyet, operasyoneldir: dış tarayıcı süreçlerini yönetirsiniz.
ÜretimPuppeteer Sharpdağıtımı, öğreticilerdeki 5 satırlık örnek kod değil, eşzamanlı PDF üretimi için gereken tarayıcı havuzu kodu olarak işte böyle görünüyor:
using PuppeteerSharp;
using System.Collections.Concurrent;
public class PdfBrowserPool : IAsyncDisposable
{
private readonly ConcurrentBag<IBrowser> _available = new();
private readonly SemaphoreSlim _semaphore;
private readonly int _maxBrowsers;
public PdfBrowserPool(int maxBrowsers = 4)
{
_maxBrowsers = maxBrowsers;
_semaphore = new SemaphoreSlim(maxBrowsers, maxBrowsers);
}
public async Task InitializeAsync()
{
await new BrowserFetcher().DownloadAsync(); // ~280MB download
for (int i = 0; i < _maxBrowsers; i++)
{
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
Args = new[] { "--no-sandbox", "--disable-setuid-sandbox",
"--disable-dev-shm-usage" }
});
_available.Add(browser);
}
}
public async Task<byte[]> ConvertHtmlToPdf(string html)
{
await _semaphore.WaitAsync();
IBrowser browser = null;
try
{
if (!_available.TryTake(out browser))
throw new InvalidOperationException("No browser available");
await using var page = await browser.NewPageAsync();
await page.SetContentAsync(html, new NavigationOptions
{
WaitUntil = new[] { WaitUntilNavigation.Networkidle0 }
});
var result = await page.PdfAsync(new PdfOptions
{
Format = PaperFormat.A4,
PrintBackground = true
});
return result;
}
catch (Exception ex) when (ex is NavigationException or TargetClosedException)
{
// Browser crashed — replace it
browser?.Dispose();
browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
Args = new[] { "--no-sandbox", "--disable-setuid-sandbox" }
});
throw; // Re-throw after recovery
}
finally
{
if (browser != null) _available.Add(browser);
_semaphore.Release();
}
}
public async ValueTask DisposeAsync()
{
foreach (var browser in _available)
{
await browser.CloseAsync();
browser.Dispose();
}
}
}
using PuppeteerSharp;
using System.Collections.Concurrent;
public class PdfBrowserPool : IAsyncDisposable
{
private readonly ConcurrentBag<IBrowser> _available = new();
private readonly SemaphoreSlim _semaphore;
private readonly int _maxBrowsers;
public PdfBrowserPool(int maxBrowsers = 4)
{
_maxBrowsers = maxBrowsers;
_semaphore = new SemaphoreSlim(maxBrowsers, maxBrowsers);
}
public async Task InitializeAsync()
{
await new BrowserFetcher().DownloadAsync(); // ~280MB download
for (int i = 0; i < _maxBrowsers; i++)
{
var browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
Args = new[] { "--no-sandbox", "--disable-setuid-sandbox",
"--disable-dev-shm-usage" }
});
_available.Add(browser);
}
}
public async Task<byte[]> ConvertHtmlToPdf(string html)
{
await _semaphore.WaitAsync();
IBrowser browser = null;
try
{
if (!_available.TryTake(out browser))
throw new InvalidOperationException("No browser available");
await using var page = await browser.NewPageAsync();
await page.SetContentAsync(html, new NavigationOptions
{
WaitUntil = new[] { WaitUntilNavigation.Networkidle0 }
});
var result = await page.PdfAsync(new PdfOptions
{
Format = PaperFormat.A4,
PrintBackground = true
});
return result;
}
catch (Exception ex) when (ex is NavigationException or TargetClosedException)
{
// Browser crashed — replace it
browser?.Dispose();
browser = await Puppeteer.LaunchAsync(new LaunchOptions
{
Headless = true,
Args = new[] { "--no-sandbox", "--disable-setuid-sandbox" }
});
throw; // Re-throw after recovery
}
finally
{
if (browser != null) _available.Add(browser);
_semaphore.Release();
}
}
public async ValueTask DisposeAsync()
{
foreach (var browser in _available)
{
await browser.CloseAsync();
browser.Dispose();
}
}
}
Imports PuppeteerSharp
Imports System.Collections.Concurrent
Imports System.Threading
Public Class PdfBrowserPool
Implements IAsyncDisposable
Private ReadOnly _available As New ConcurrentBag(Of IBrowser)()
Private ReadOnly _semaphore As SemaphoreSlim
Private ReadOnly _maxBrowsers As Integer
Public Sub New(Optional maxBrowsers As Integer = 4)
_maxBrowsers = maxBrowsers
_semaphore = New SemaphoreSlim(maxBrowsers, maxBrowsers)
End Sub
Public Async Function InitializeAsync() As Task
Await (New BrowserFetcher()).DownloadAsync() ' ~280MB download
For i As Integer = 0 To _maxBrowsers - 1
Dim browser = Await Puppeteer.LaunchAsync(New LaunchOptions With {
.Headless = True,
.Args = New String() {"--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage"}
})
_available.Add(browser)
Next
End Function
Public Async Function ConvertHtmlToPdf(html As String) As Task(Of Byte())
Await _semaphore.WaitAsync()
Dim browser As IBrowser = Nothing
Try
If Not _available.TryTake(browser) Then
Throw New InvalidOperationException("No browser available")
End If
Await Using page = Await browser.NewPageAsync()
Await page.SetContentAsync(html, New NavigationOptions With {
.WaitUntil = New WaitUntilNavigation() {WaitUntilNavigation.Networkidle0}
})
Dim result = Await page.PdfAsync(New PdfOptions With {
.Format = PaperFormat.A4,
.PrintBackground = True
})
Return result
End Using
Catch ex As Exception When TypeOf ex Is NavigationException OrElse TypeOf ex Is TargetClosedException
' Browser crashed — replace it
browser?.Dispose()
browser = Await Puppeteer.LaunchAsync(New LaunchOptions With {
.Headless = True,
.Args = New String() {"--no-sandbox", "--disable-setuid-sandbox"}
})
Throw ' Re-throw after recovery
Finally
If browser IsNot Nothing Then _available.Add(browser)
_semaphore.Release()
End Try
End Function
Public Async Function DisposeAsync() As ValueTask Implements IAsyncDisposable.DisposeAsync
For Each browser In _available
Await browser.CloseAsync()
browser.Dispose()
Next
End Function
End Class
Bu, tek bir PDF üretmeden önce ~60 satır altyapı kodudur. Ayrıca bellek sızıntısı izlemesi (Zamanla Chromium süreçleri bellek biriktirir), sağlık kontrolleri ve 20+ Chromium bağımlılığı ile bir Dockerfile gereklidir. Docker görüntü boyutu 300–400MB artar.
Bunu eşdeğerIronPDFyaklaşımı ile karşılaştırın:
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Browser pooling, process management, crash recovery — handled internally
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Browser pooling, process management, crash recovery — handled internally
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
' Browser pooling, process management, crash recovery — handled internally
Puppeteer Sharp, ekibiniz operasyonel yükü absorbe edebilirse uygulanabilir. Tarayıcı altyapısına değil uygulamaya odaklanmak isteyen ekipler içinIronPDFaynı render işlemini dahili olarak ele alır.
QuestPDFNeden HTML'yi Dönüştüremez?
QuestPDF, Reddit ve Stack Overflow'da neredeyse her 'HTML to PDF C#' tartışmasında görünmektedir. Bu tutarlı bir model oluşturur: geliştiriciler HTML dönüştürme bekleyerek QuestPDF'yi satın alır veya entegre eder, ardından hiç HTML render etmediğini keşfeder.
QuestPDF programatik belge oluşturma için akıcı bir C# API'sidir. Pozisyonu açıkça 'HTML-to-PDF dönüşümüyle mücadele etmemeyi bırak' şeklindedir — HTML yaklaşımını C# kodu ile değiştirir. Bu kasti bir tasarım tercihi. 2022 ile 2024 arasındaki GitHub tartışmaları geliştiricilerin bu durumu uygulanmayı başlattıklarında keşfettiklerini göstermektedir. Yönetici ekibi sürekli olarak HTML desteğinin planlanmadığını doğrular.
Mevcut iş akışınızda HTML şablonlar — faturalar için Razor görünümleri, raporlar için gösterge paneli HTML'leri, arşivleme için web içeriği — kullanılıyorsa,QuestPDFher şablonu C# akıcı API kodu olarak yeniden yazmayı gerektirir. Yapılandırılmış verilerle sıfırdan belge düzenleri oluşturduğunuz yeni projeler için QuestPDF'nin API'si iyi tasarlanmış ve etkili.
Topluluk Lisansı, yıllık brüt geliri 1M$ altında olan işletmeleri kapsar. Bunun üzerinde ticari lisanslama gereklidir.
Aspose.PDF Ne Durumda?
Aspose.PDF, ticari lisanslama ile geniş bir PDF işlevselliği sağlar (geliştirici başına ~999 dolardan başlar). HTML dönüştürme, bir tarayıcı yerine özel bir motor kullanmaktadır — iText'e benzer biçimde, temel HTML'i işler ancak modern CSS özelliklerini doğru bir şekilde render etmez.
Asıl endişe platform istikrarıdır: Aspose, Linux üzerinde libgdiplus gerektiren System.Drawing.Common'a dayanır. Microsoft, bunu .NET 6+ üzerindeki non-Windows platformları için kullanımdan kaldırdı. Geliştiriciler, Windows üzerinde meydana gelmeyen Linux dağıtımlarına özgü bellek sızıntılarını bildirir. Yalnızca Windows ortamları için Aspose, yeterlidir. Çapraz platform ya da konteynırlaştırılmış dağıtımlar için bağımlılık zinciri sürekli risk yaratır.
IronPDFHTML-to-PDF Dönüşümünü Nasıl Yönetir?
IronPDF, Chromium'u doğrudan NuGet paketine gömüyor. CSS Flexbox, Grid, özel özellikler, @font-face, medya sorguları ve JavaScript, Chrome'da olduğu gibi çalışır. Çıktı tarayıcı ile eşleşir çünkü aynı render motorunu kullanır.
using IronPdf;
var renderer = new ChromePdfRenderer();
string html = @"
<!DOCTYPE html>
<html>
<head>
<style>
:root { --primary: #2563eb; }
body { font-family: 'Segoe UI', sans-serif; padding: 40px; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 20px; }
.card {
background: linear-gradient(135deg, #f8fafc, #e2e8f0);
border-radius: 12px; padding: 24px; text-align: center;
}
.card h3 { color: #6b7280; font-size: 0.8rem; text-transform: uppercase; margin: 0; }
.card .value { font-size: 2rem; font-weight: 700; color: var(--primary); }
table { width: 100%; border-collapse: collapse; margin-top: 30px; }
th { background: var(--primary); color: white; padding: 12px; text-align: left; }
td { padding: 10px; border-bottom: 1px solid #e5e7eb; }
</style>
</head>
<body>
<div class='grid'>
<div class='card'><h3>Revenue</h3><div class='value'>$1.2M</div></div>
<div class='card'><h3>Users</h3><div class='value'>45,230</div></div>
<div class='card'><h3>Uptime</h3><div class='value'>99.97%</div></div>
</div>
<table>
<tr><th>Product</th><th>Revenue</th><th>Growth</th></tr>
<tr><td>Enterprise</td><td>$680K</td><td>+12%</td></tr>
<tr><td>Professional</td><td>$356K</td><td>+8%</td></tr>
</table>
</body>
</html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("report.pdf");
using IronPdf;
var renderer = new ChromePdfRenderer();
string html = @"
<!DOCTYPE html>
<html>
<head>
<style>
:root { --primary: #2563eb; }
body { font-family: 'Segoe UI', sans-serif; padding: 40px; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 20px; }
.card {
background: linear-gradient(135deg, #f8fafc, #e2e8f0);
border-radius: 12px; padding: 24px; text-align: center;
}
.card h3 { color: #6b7280; font-size: 0.8rem; text-transform: uppercase; margin: 0; }
.card .value { font-size: 2rem; font-weight: 700; color: var(--primary); }
table { width: 100%; border-collapse: collapse; margin-top: 30px; }
th { background: var(--primary); color: white; padding: 12px; text-align: left; }
td { padding: 10px; border-bottom: 1px solid #e5e7eb; }
</style>
</head>
<body>
<div class='grid'>
<div class='card'><h3>Revenue</h3><div class='value'>$1.2M</div></div>
<div class='card'><h3>Users</h3><div class='value'>45,230</div></div>
<div class='card'><h3>Uptime</h3><div class='value'>99.97%</div></div>
</div>
<table>
<tr><th>Product</th><th>Revenue</th><th>Growth</th></tr>
<tr><td>Enterprise</td><td>$680K</td><td>+12%</td></tr>
<tr><td>Professional</td><td>$356K</td><td>+8%</td></tr>
</table>
</body>
</html>";
var pdf = renderer.RenderHtmlAsPdf(html);
pdf.SaveAs("report.pdf");
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
Dim html As String = "
<!DOCTYPE html>
<html>
<head>
<style>
:root { --primary: #2563eb; }
body { font-family: 'Segoe UI', sans-serif; padding: 40px; }
.grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 20px; }
.card {
background: linear-gradient(135deg, #f8fafc, #e2e8f0);
border-radius: 12px; padding: 24px; text-align: center;
}
.card h3 { color: #6b7280; font-size: 0.8rem; text-transform: uppercase; margin: 0; }
.card .value { font-size: 2rem; font-weight: 700; color: var(--primary); }
table { width: 100%; border-collapse: collapse; margin-top: 30px; }
th { background: var(--primary); color: white; padding: 12px; text-align: left; }
td { padding: 10px; border-bottom: 1px solid #e5e7eb; }
</style>
</head>
<body>
<div class='grid'>
<div class='card'><h3>Revenue</h3><div class='value'>$1.2M</div></div>
<div class='card'><h3>Users</h3><div class='value'>45,230</div></div>
<div class='card'><h3>Uptime</h3><div class='value'>99.97%</div></div>
</div>
<table>
<tr><th>Product</th><th>Revenue</th><th>Growth</th></tr>
<tr><td>Enterprise</td><td>$680K</td><td>+12%</td></tr>
<tr><td>Professional</td><td>$356K</td><td>+8%</td></tr>
</table>
</body>
</html>"
Dim pdf = renderer.RenderHtmlAsPdf(html)
pdf.SaveAs("report.pdf")
Bu, minmax, özel özellikler, linear-gradient, border-radius ve :root seçicileri ile CSS Grid kullanır. Bu özelliklerin her biri iText'in pdfHTML'inde başarısız olur, wkhtmltopdf'de bozulur ve PdfSharp veya QuestPDF'de mevcut değildir.
Diğer Kütüphanelerden Nasıl Geçiş Yapılır?
iText veya wkhtmltopdf'den geçen ekipler için,IronPDFdoğrudan URL'leri kabul eder — mevcut iş akışınız HTML dosyaları oluşturduğunda veya sayfalar sunduğunda kullanışlıdır:
using IronPdf;
var renderer = new ChromePdfRenderer();
// Convert from URL — useful when migrating fromwkhtmltopdfURL-based workflows
var pdf = renderer.RenderUrlAsPdf("https://localhost:5001/reports/quarterly");
pdf.SaveAs("report.pdf");
// Convert from local HTML file
var pdfFromFile = renderer.RenderHtmlFileAsPdf("templates/invoice.html");
pdfFromFile.SaveAs("invoice.pdf");
using IronPdf;
var renderer = new ChromePdfRenderer();
// Convert from URL — useful when migrating fromwkhtmltopdfURL-based workflows
var pdf = renderer.RenderUrlAsPdf("https://localhost:5001/reports/quarterly");
pdf.SaveAs("report.pdf");
// Convert from local HTML file
var pdfFromFile = renderer.RenderHtmlFileAsPdf("templates/invoice.html");
pdfFromFile.SaveAs("invoice.pdf");
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
' Convert from URL — useful when migrating from wkhtmltopdf URL-based workflows
Dim pdf = renderer.RenderUrlAsPdf("https://localhost:5001/reports/quarterly")
pdf.SaveAs("report.pdf")
' Convert from local HTML file
Dim pdfFromFile = renderer.RenderHtmlFileAsPdf("templates/invoice.html")
pdfFromFile.SaveAs("invoice.pdf")
Kullanım
IronPDF, Windows (x64), Linux (x64, ARM64), macOS (x64, Apple Silicon) ve Docker konteynerlerinde çalışır. Docker yapılandırması standart bir .NET görüntüsüdür:
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY . .
ENTRYPOINT ["dotnet", "MyApp.dll"]
Chromium kurulumu yok, yerel kütüphane bağımlılıkları yok, sandbox yapılandırması yok.
Lisanslama: $2,998'dan başlayan Süresiz Lisanslar. ironpdf.com adresinde yayınlanan fiyatlar. AGPL yok, belge başına ücret yok, gelir eşik limitleri yok.
Performans Kıyaslamaları
Ubuntu 22.04 ve .NET 8 çalıştıran bir Standard_D4s_v3 Azure VM (4 vCPU, 16GB RAM) üzerinde test edildi. Test belgesi: CSS Grid düzeni, gömülü resimler ve JavaScript tarafından üretilen bir grafik içeren 200 öğelik bir HTML fatura şablonu. Ölçümlerin her biri, 5 yineleme ısınma döneminin ardından 50 yineleme üzerinde ortalamasını aldık.
| Senaryo | IronPDF | Puppeteer Sharp | iText pdfHTML | wkhtmltopdf |
|---|---|---|---|---|
| Basit HTML (JS olmadan) | ~150ms | ~500ms | ~200ms | ~200ms |
| Karmaşık CSS (Flexbox/Grid) | ~250ms | ~600ms | Bozuk çıktı | Bozuk çıktı |
| JavaScript-render edilmiş içerik | ~350ms | ~800ms | Başarısız (JS motoru yok) | Başarısız/Kısmi |
| İşlem başına bellek | ~80MB | ~150MB | ~60MB | ~50MB |
| Soğuk başlangıç (ilk nesil) | 2-5s | 3-8s | <1s | <1s |
iText vewkhtmltopdfdaha hızlı soğuk başlatma süreleri gösterir çünkü bir tarayıcı motoru başlatmazlar. Ancak bu karşılaştırma yalnızca tüm kütüphanelerin doğru çıktı ürettiği senaryolar için anlamlıdır — ve karmaşık CSS veya JavaScript içeriği için, yalnızcaIronPDFvePuppeteer Sharpkullanılabilir sonuçlar üretir.
Not: Bunlar belirtilen donanım üzerindeki tipik gözlemleri temsil eder. Performansınız, HTML karmaşıklığı, belge uzunluğu ve sunucu kaynaklarıyla değişiklik gösterecektir. Gerçek iş yüklerinizi test etmeden önce kararlar vermeyin.
Özellik Karşılaştırması
| Özellik | IronPDF | iText | Puppeteer Sharp | wkhtmltopdf | PDFSharp | QuestPDF | Aspose |
|---|---|---|---|---|---|---|---|
| HTML'den PDF'ye | Evet (Chromium) | Sınırlı (CSS 2.1) | Evet (Chrome) | Kullanım dışı | Hayır | Hayır | Sınırlı |
| CSS Flexbox/Grid | Evet | Hayır | Evet | Hayır | Hayır | Hayır | Hayır |
| JavaScript yürütme | Evet | Hayır | Evet | Sınırlı | Hayır | Hayır | Hayır |
| Çapraz platform (libgdiplus yok) | Evet | Evet | Evet | Yok | Kısmi | Evet | Hayır |
| Yayınlanmış fiyatlandırma | $2,998+ | Hayır ($15K–$210K/yıl) | Ücretsiz (MIT) | Ücretsiz | Ücretsiz (MIT) | Ücretsiz <$1M | 999$+ |
| Aktif bakım | Evet | Evet | Evet | Terkedilmiş | Evet | Evet | Evet |
Hangi Kütüphaneyi Seçmeliyim?
Modern CSS ile HTML şablonları → IronPDF, dış işlem yönetimi olmadan gömülü Chromium sağlar. Ekibiniz tarayıcı altyapısını yönetebiliyorsa,Puppeteer Sharpuygun bir alternatif.
Verilere dayalı, HTML'siz programatik belge oluşturma → QuestPDF, zarif bir akıcı API sunar. HTML dönüşümü bekleyerek tercih etmeyin.
Basit PDF manipülasyonu (birleştirme, bölme, filigran) → PDFSharp ücretsizdir ve HTML dışı görevler için yeteneklidir.
Yeni projeler için kaçınılacaklar:wkhtmltopdf(terk edilmiş, CVE'ler), ticari lisans olmadaniText(AGPL tuzağı), Linux üzerindeAspose(bellek sızıntıları).
Asıl soru, iş akışınızın HTML şablonları kullanıp kullanmadığıdır. Eğer kullanıyorsa, yalnızca Chromium tabanlı çözümler modern CSS ile doğru çıktı üretir. Eğer kullanmıyorsa, tercih API tercihi ve lisanslama kısıtlamalarına bağlıdır.