C#'ta HTML'den PDF'ye - Kütüphane Seçeneklerinin Gerçekliği
C#'da HTML'yi PDF'e dönüştürmek, gercekten HTML'yi isleyecek bir kutuphane gerektirir — etiketlerin bir alt kumesini koklamayan ve CSS 2.1'i yaklasiklayan biri değil. Stack Overflow konulari ve Reddit tartismalarinda tavsiye edilen kutuphanelerin cogu modern CSS'yi yorumlayamaz, ticari kullanim icin diskalifiye edici lisans kisitlamalari tasir veya yamalanmayan guvenlik aciklariyla terk edilmistir.
Bu makale, "HTML to PDF C#" icin arasir yaptiklarinda geliştiricilerin gercekten karsilasabilecegi kutuphaneleri karsilastirir, her birinin neleri yapip neleri yapamayacagini belgelendirir, metodolojisi ile performans karsilastirma tablolarini icerir ve her yaklasimin gerçek operasyonel maliyetini gösterir.
Quickstart:HTML'den PDF'yein 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 ile yükleyin: Install-Package IronPDF. Windows, Linux, macOS ve Docker'a harici bagimliliklar olmadan dağıtir.
Neden HTML'den PDF'e Dönüştürme Zor?
HTML'yi dogru bir sekilde PDF'e işlemek, bir web tarayicisinin kullandigi bes bileşeni uygulamayi gerektirir: bir HTML ayrıştırıcı, bir CSS motoru (Flexbox, Grid, kaskad, özelik ve medya sorgulari dahil), bir JavaScript calisma zamani, bir düĢey motoru ve tüm bunları PDF'e alt piksel doğrulukla birleştiren bir işleme hattı.
Geleneksel PDF kutuphaneleri ilk ikisini kısmen uygular ve JavaScript'i tamamen atlar. Bu yüzden basit HTML'yi işlerler ama modern bir tarayıcının doğru bir şekilde render ettiği herhangi birşeye dayanamazlar. Tarayıcı çıktısıyla eşleşmenin tek yolu, bir tarayıcı motoru kullanmaktır.
Aslında Hangi Kutuphaneler HTML'yi PDF'e Dönüştürur?
wkhtmltopdf Sargıları — DLL Yükleme Hatası Ekosistemi
Bu makalelere geliştirici getiren en yaygin arama sorgusu bir varyasyonu sunar:
System.DllNotFoundException: DLL 'libwkhtmltox' yuklenemediPlatforma özgü değişkenler şunları içerir:
'wkhtmltox' veya bagimliliklardan biri olan paylasilan kutuphane yuklenemiyor
(Linux — libwkhtmltox.so not found)
Belirtilen modul bulunamadi. (0x8007007E)
(Windows — wkhtmltox.dll path not configured)
dyld: Kutuphane yuklenemedi: libwkhtmltox.dylib
(macOS — not supported on ARM64/Apple Silicon)Bu hatalar DinkToPdf, NReco.PdfGenerator, WkHtmlToXSharp ve ayni terkedilmis binari etrafinda C# sargilari oluşturan diğer urunlerden gelir. wkhtmltopdf GitHub organizasyonu Temmuz 2024'te arsive eklendi. Altta yatan QtWebKit motoru, Qt tarafindan 2015'te kullanıma kapatıldı. proje durum sayfası açik bir sekilde kullanımdan kaldirildi olarak isaretlenmistir.
DLL yükleme sorunlarinin utesinde, görüntüleme motoru yaklasik Safari 2011 yeteneginde donduruldu. Flexbox yok, Grid yok, sinirli CSS3, guvenilmez JavaScript. Ve yamalanmayan kritik guvenlik aciklari vardir: CVE-2022-35583(CVSS 9.8), ozenle hazirlanan HTML araciligiyla AWS kimlik bilgilerini celme edebilecek SSRF saldırılarını etkinlestirir.
wkhtmltopdf'nin zamanı geçti. DLL yükleme hataları daha derin bir sorunun belirtileridir: ilerleme yolu olmayan terkedilmis yazilima bagimli oluyorsunuz.
iText 7 (pdfHTML Eklentisi) — Sinirli CSS, AGPL Lisansli
iText'in pdfHTML modulu HTML'yi bir özel ayrıştırıcı kullanarak PDF'e dönüştürur — bir tarayıcı motoru degildir. Temel HTML/CSS'yi ele alır ancak Flexbox, Grid veya JavaScript'i işleyemez.
Hata modlari sessiz: pdfHTML desteklenmeyen CSS ile karsilastiginda istisnalar atmaz. Yapabileceklerini render eder ve geri kalanını yoksayar. display: flex konteyneri gap: 20px ve justify-content: space-between ile boşluksuz olarak dikey istiflenmiş elemanlar olarak render edilir. Gelisticiler bunu entegrasyon sonra, değil daha önce kesfederler.
Lisanslama: AGPL — uygulamanizin tüm agir network erişimli uygulamanizi acik kaynak yapmanizi veya ticari lisans satisinizi gerektirir. Fiyatlandırma yayınlanmamıştır; ucuncu taraf verileri yıllık $15,000–$210,000 oldugunu önermektedir.
Hafıza Kullanımı Nasıl Karsilastirilir?
iText'in pdfHTML modulu işleme icin tüm belgeleri hafizaya yukler. Tipik ticari belgeler icin bu yönetilebilir, ancak iceriğe sahip gömülü goruntüler ile buyuk HTML raporlari, görüntüleme yaklasimlarina karsi onemli hafiza baskisi yaratabilir.
NedenPdfSharpHTML'yi Desteklemiyor?
PdfSharp, popülerliği (34.9 milyon NuGet indirme) ve sık önerilmesi nedeniyle "HTML to PDF" arama sonuçlarında görünür. Ancak PdfSharp HTML ayrıştırıcısı yoktur. Koordinat tabanlı bir çizim API'si sağlar: DrawString(), DrawRectangle(), DrawImage() ile açık X/Y pozisyonları.
Sıkça önerilen geçici çözüm, HtmlRenderer.PdfSharp, yalnızca HTML 4.01 ve CSS Level 2'yi destekler. Eğer HTML'iniz 2010'dan sonra tanıtılmış bir CSS özelliği kullanıyorsa — Flexbox (2012), Grid (2017), özel özellikler (2017), border-radius (2011) — render edilmeyecektir.
HTML desteği bekleyerek PdfSharp seçen geliştiriciler, ya her bir elemanı koordinat tabanlı kodla manuel olarak konumlandırır ya da HTML renderleme için ikinci bir kütüphane eklerler — bu noktada PdfSharp gereksiz hale gelir.
Puppeteer Sharp'i Nasıl Kaynak Sert Yapan?
Puppeteer Sharp başsız Chrome'u .NET bağlamaları aracılığıyla kontrol eder. Görüntüleme dogrulugu Chrome ile eslesir, cunku o Chrome'dur. Maliyet operasyoneldir: harici tarayici sureclerini siz yonetirsiniz.
IsletmedekiPuppeteer Sharpdagitimi aslen ornegi izgara görüntülu bir sekline suruyle PDF oluşturumak icin tarayici havuzlama kodunu gerektirir.
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 ClassBir tek PDF oluşturmadan once ~60 satir alt yapi kodudur. Ayrica hafiza sızıntı izlemesi (Chromium is sur leleri zamanla hafiza alikoyar), saglik kontrolleri ve 20+ Chromium bagimliliklari olan bir Dockerfile'a ihtiyaç duyarsiniz. Docker imaj boyutu 300–400MB artis gösterir.
Bu, esdegerIronPDFyaklasimi ile karsilastirilir:
using IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Browser pooling, process management, crash recovery — handled internallyusing IronPdf;
var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Browser pooling, process management, crash recovery — handled internallyImports IronPdf
Dim renderer As New ChromePdfRenderer()
Dim pdf = renderer.RenderHtmlAsPdf(html)
' Browser pooling, process management, crash recovery — handled internallyEkibiniz operasyonel yükleri absorbe edebilirsePuppeteer Sharpuygulanabilir. Tarayici alt yapi isine odaklanmaktan çok uygulamalarina odaklanmak isteyen takimlar icin,IronPDFayni işleme dahili olarak yonetir.
NedenQuestPDFHTML Dönüştüremez?
QuestPDF hemen her Reddit ve Stack Overflow 'HTML to PDF C#' tartismasinda gorunur. Bu surekli bir model yaratir: geliştiriciler, HTML donusumu beklentisiyle QuestPDF'i satin alir veya birlestirir, sonra HTML'yi hic yorumlamadigini kesfederler.
QuestPDF, programatik dokumen oluşturmak icin bir akici C# API'sidir. Konumlandirilmasi, "HTML to PDF donusumuyle mucadeleyi durdurun" acik bir sekilde — HTML yaklasimi C# kodu ile değiştirir. Bu, kasten bir tasarim secimi. GitHub tartısmaları 2022'den 2024'e kadar bu kesfin başlangicinda geliştiricilerin kesfettigini gösterir. Bakimcilar sürekli olarak HTML desteginin planlanmadigini dogruluyor.
Mesaî mevcut iş akışı HTML şablonlarını kullaniyorsa — faturalar icin Razor görünümleri, raporlar icin pano HTML'ler, arsivleme icin web içeriği —QuestPDFher şablonu C# akici API koduyla yeniden yonetmez. Yeni projelerde belgeleri sıfırdan yaparken,QuestPDFAPI'si iyi tasarlanmis ve verimlidir.
Baglam Izin Koleji, $1M EGT altinda isletmeleri kapsar. Bunun üzerinde, ticari lisans zorunludur.
Aspose.PDF Hakkında Ne Söyleyebiliriz?
Aspose.PDF, ticari lisanslama ile geniş PDF işlevselliği sağlar (başlangıç ~999$/geliştirici). HTML dönüşümü, bir tarayıcı yerine özel bir motor kullanır — iText'e benzer şekilde, temel HTML'yi işler ancak modern CSS özelliklerini doğru şekilde işleyemez.
Asıl endişe platformun kararlılığıdır: Aspose, Linux'ta libgdiplus gerektiren System.Drawing.Common'e bağlıdır. Microsoft, .NET 6+ için bu durumu Windows dışı platformlarda devre dışı bıraktı. Geliştiriciler, Windows'ta meydana gelmeyen Linux dağıtımlarına özgü bellek sızıntılarını rapor etmektedir. Yalnızca Windows ortamları için,Asposeyeteneklidir. Platformlar arası veya konteyner tabanlı dağıtımlar için, bağımlılık zinciri sürekli bir risk oluşturur.
IronPDFHTML'den PDF'e Dönüşümü Nasıl Ele Alır?
IronPDF, NuGet paketinde Chromium'u dogrudan gomer. CSS Flexbox, Grid, özel özellikler, @font-face, medya sorguları ve JavaScript Chrome'da olduğu gibi çalışır. Çıktı, aynı işleme motorunu kullandığından tarayıcı ile aynı olur.
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, CSS Grid'i minmax ile, özel özellikler, linear-gradient, border-radius ve :root seçicileriyle kullanır. Bu özelliklerin her biri iText'in pdfHTML'sinde başarısız olur, wkhtmltopdf'te kırılır ve PdfSharp veya QuestPDF'de mevcut değildir.
Diğer Kütüphanelerden Nasıl Geçiş Yaparım?
iTextSharp veya wkhtmltopdf'den geçiş yapan ekipler için,IronPDFURL'leri doğrudan kabul eder — HTML dosyaları oluşturduğunuzda veya sayfalar sunduğunuzda yararlı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")Dağıtım
IronPDF, Windows (x64), Linux (x64, ARM64), macOS (x64, Apple Silicon) ve Docker konteynerlerinde çalışır. Docker konfigürasyonu standart bir .NET imajı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ığı yok, sandbox konfigürasyonu yok.
Lisanslama: Sonsuz lisanslar 749$'dan başlar. Yayınlanan fiyatlar ironpdf.com adresinde. AGPL yok, belge başına ücret yok, gelir eşiği yok.
Performans Karşılaştırmaları
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ü görüntüler ve JavaScript ile üretilmiş bir grafik içeren 200 öğelik HTML fatura şablonu. Her ölçüm, 5 deneme ısınma döneminden sonra 50 yineleme üzerinden ortalaması alınmıştır.
| Senaryo | IronPDF | Puppeteer Sharp | iText pdfHTML | wkhtmltopdf |
|---|---|---|---|---|
| Basit HTML (JS yok) | ~150ms | ~500ms | ~200ms | ~200ms |
| Karmaşık CSS (Flexbox/Grid) | ~250ms | ~600ms | Bozuk çıktı | Bozuk çıktı |
| JavaScript ile oluşturulan içerik | ~350ms | ~800ms | Başarısız (JS motoru yok) | Başarısız/Parçalı |
| Her işlem başına bellek | ~80MB | ~150MB | ~60MB | ~50MB |
| Soğuk başlangıç (ilk nesil) | 2–5s | 3–8s | <1s | <1s |
iText ve wkhtmltopdf, tarayıcı motorunu başlatmadıkları için daha hızlı soğuk başlangıç süreleri gösterir. Ancak bu karşılaştırma, tüm kütüphanelerin doğru çıktı ürettiği senaryolar için anlamlıdır — ve karmaşık CSS veya JavaScript içeriğinde, yalnızcaIronPDFvePuppeteer Sharpkullanılabilir sonuçlar üretir.
Not: Belirtilen donanımda tipik gözlemleri temsil eder. Performansınız, HTML karmaşıklığı, belge uzunluğu ve sunucu kaynakları ile değişiklik gösterecektir. Karar vermeden önce gerçek iş yüklerinizle test yapın.
Özellik Karşılaştırması
| Özellik | IronPDF | iText 7 | Puppeteer Sharp | wkhtmltopdf | PdfSharp | QuestPDF | Aspose |
|---|---|---|---|---|---|---|---|
| HTML'den PDF'ye | Evet (Chromium) | Sınırlı (CSS 2.1) | Evet (Chrome) | Kullanımdan kaldırılmış | Hayır | Hayır | Sınırlı |
| CSS Flexbox/Grid | Evet | Hayır | Evet | Hayır | Hayır | Hayır | Hayır |
| JavaScript çalıştırma | Evet | Hayır | Evet | Sınırlı | Hayır | Hayır | Hayır |
| Platformlar arası (libgdiplus yok) | Evet | Evet | Evet | N/A | Kısmen | Evet | Hayır |
| Yayınlanmış fiyatlandırma | $749+ | Hayır (15K-210K $/yıl) | Ücretsiz (MIT) | Ücretsiz | Ücretsiz (MIT) | Ücretsiz <$1M | $999+ |
| Aktif bakım | Evet | Evet | Evet | Terk edilmiş | Evet | Evet | Evet |
Hangi Kütüphaneyi Seçmeliyim?
Modern CSS ile HTML şablonları → IronPDF harici süreç yönetimi olmaksızın gömülü Chromium sağlar. Eğer ekibiniz tarayıcı altyapısını yönetebilirse,Puppeteer Sharpgeçerli bir alternatiftir.
Verilerden programatik belge oluşturma, HTML yok → QuestPDF şık bir akıcı API sunar. HTML dönüştürme beklemeyin.
Basit PDF manipülasyonu (birleşme, bölme, filigran) → PdfSharp HTML dışı görevler için ücretsiz ve yeteneklidir.
Yeni projelerden kaçının:wkhtmltopdf(terk edilmiş, CVE'ler), iText ticari lisans olmadan (AGPL tuzağı), Linux üzerindeAspose(bellek sızıntıları).
Anahtar soru, iş akışınızın HTML şablonlarını 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, seçim API tercihi ve lisans kısıtlamalarına bağlıdır.
