VERGLEICH

HTML zu PDF in C# - Die Realität der Bibliotheksoptionen

Die Konvertierung von HTML in PDF in C# erfordert eine Bibliothek, die HTML tatsächlich rendert - und nicht eine, die eine Teilmenge von Tags analysiert und CSS 2.1 annähert. Die meisten Bibliotheken, die in Stack Overflow-Threads und Reddit-Diskussionen empfohlen werden, können entweder kein modernes CSS rendern, unterliegen Lizenzbeschränkungen, die sie für die kommerzielle Nutzung disqualifizieren, oder wurden mit ungepatchten Sicherheitslücken aufgegeben.

Dieser Artikel vergleicht die Bibliotheken, auf die Entwickler tatsächlich stoßen, wenn sie nach "HTML to PDF C#" suchen, dokumentiert, was jede von ihnen rendern kann und was nicht, enthält Leistungs-Benchmarks mit Methodik und zeigt die tatsächlichen Betriebskosten der einzelnen Ansätze.

Schnellstart: HTML zu PDF 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")
$vbLabelText   $csharpLabel

Installation über NuGet: Install-Package IronPDF. Lässt sich ohne externe Abhängigkeiten auf Windows, Linux, macOS und Docker installieren.

Warum ist die HTML-zu-PDF-Konvertierung so schwierig?

Das korrekte Rendern von HTML in PDF erfordert die Implementierung derselben fünf Komponenten, die auch ein Webbrowser verwendet: einen HTML-Parser, eine CSS-Engine (einschließlich Flexbox, Grid, Cascade, Spezifität und Media-Queries), eine JavaScript-Laufzeitumgebung, eine Layout-Engine und eine Rendering-Pipeline, die all dies mit Subpixel-Genauigkeit zu PDF zusammensetzt.

Herkömmliche PDF-Bibliotheken implementieren die ersten beiden teilweise und lassen JavaScript ganz weg. Aus diesem Grund kommen sie mit einfachem HTML zurecht, versagen aber bei allem, was ein moderner Browser korrekt wiedergibt. Die einzige Möglichkeit, die Browserausgabe anzupassen, ist die Verwendung einer Browser-Engine.

Welche Bibliotheken konvertieren tatsächlich HTML in PDF?

wkhtmltopdf Wrappers - Das DLL-Ladefehler-Ökosystem

Die häufigste Suchanfrage, die Entwickler zu diesen Artikeln führt, ist eine Variation von:

System.DllNotFoundException: DLL 'libwkhtmltox' kann nicht geladen werden

Zu den plattformspezifischen Varianten gehören:

Gemeinsame Bibliothek 'wkhtmltox' oder eine ihrer Abhängigkeiten kann nicht geladen werden
    (Linux — libwkhtmltox.so not found)

Das angegebene Modul konnte nicht gefunden werden. (0x8007007E)
    (Windows — wkhtmltox.dll path not configured)

dyld: Bibliothek nicht geladen: libwkhtmltox.dylib
    (macOS — not supported on ARM64/Apple Silicon)

Diese Fehler stammen von DinkToPdf, NReco.PdfGenerator, WkHtmlToXSharp und anderen C#-Wrappern um das gleiche verlassene Binary. Die wkhtmltopdf GitHub Organisation wurde im Juli 2024 archiviert. Die zugrunde liegende QtWebKit-Engine wurde 2015 von Qt veraltet. Die Projektstatusseite kennzeichnet sie ausdrücklich als veraltet.

Abgesehen von den DLL-Ladeproblemen ist die Rendering-Engine ungefähr auf dem Stand von Safari 2011 eingefroren. Kein Flexbox, kein Grid, begrenztes CSS3, unzuverlässiges JavaScript. Und es gibt ungepatchte kritische Sicherheitslücken: CVE-2022-35583(CVSS 9.8) ermöglicht SSRF-Angriffe, mit denen AWS-Anmeldedaten über manipuliertes HTML exfiltriert werden können.

die Zeit von wkhtmltopdf ist vorbei. Die DLL-Ladefehler sind ein Symptom für ein tiefer liegendes Problem: Sie sind von einer verlassenen Software abhängig, für die es keinen Ausweg gibt.

iText 7 (pdfHTML Add-On) - Eingeschränktes CSS, AGPL lizenziert

das pdfHTML-Modul von iText konvertiert HTML in PDF unter Verwendung eines benutzerdefinierten Parsers - nicht einer Browser-Engine. Es verarbeitet grundlegende HTML/CSS-Funktionen, rendert aber nicht Flexbox, Grid oder JavaScript.

Der Fehlermodus ist still: pdfHTML löst keine Ausnahmen aus, wenn es auf nicht unterstütztes CSS stößt. Sie rendert, was sie kann, und ignoriert den Rest. Ein display: flex Container mit gap: 20px und justify-content: space-between wird als vertikal gestapelte Elemente ohne Abstand dargestellt. Die Entwickler entdecken dies nach der Integration, nicht währenddessen.

Lizenzierung: AGPL - erfordert das Open-Sourcing Ihrer gesamten über das Netz zugänglichen Anwendung oder den Erwerb einer kommerziellen Lizenz. Preisangaben werden nicht veröffentlicht; die Daten von Drittanbietern deuten auf $15.000-$210.000 jährlich hin.

Wie ist die Speichernutzung im Vergleich?

pdfHTML von iText lädt das gesamte Dokument zur Verarbeitung in den Speicher. Für typische Geschäftsdokumente ist dies überschaubar, aber große HTML-Berichte mit eingebetteten Bildern können im Vergleich zu Streaming-Ansätzen einen erheblichen Speicherdruck verursachen.

Warum unterstützt PdfSharp kein HTML?

PdfSharp erscheint aufgrund seiner Beliebtheit (34,9 Millionen NuGet-Downloads) und häufiger Empfehlungen in den Suchergebnissen für "HTML to PDF". Aber PdfSharp hat keinen HTML-Parser. Es bietet eine koordinatenbasierte Zeichen-API: DrawString(), DrawRectangle(), DrawImage() mit expliziten X/Y-Positionen.

Der allgemein vorgeschlagene Workaround, HtmlRenderer.PdfSharp, unterstützt nur HTML 4.01 und CSS Level 2. Wenn Ihr HTML-Code eine CSS-Funktion verwendet, die nach 2010 eingeführt wurde - Flexbox (2012), Grid (2017), benutzerdefinierte Eigenschaften (2017), border-radius (2011) - wird er nicht gerendert.

Entwickler, die PdfSharp in der Erwartung wählen, dass es HTML unterstützt, müssen entweder jedes Element manuell mit koordinatenbasiertem Code positionieren oder eine zweite Bibliothek für das HTML-Rendering hinzufügen - an diesem Punkt ist PdfSharp überflüssig.

Was macht Puppeteer Sharpressourcenintensiv?

Puppeteer Sharp steuert Headless Chrome über .NET-Bindungen. Die Wiedergabegenauigkeit entspricht Chrome, weil es Chrome ist. Die Kosten sind operativ: Sie verwalten externe Browserprozesse.

So sieht ein produktiver Einsatz von Puppeteer Sharpaus - nicht das 5-Zeilen-Beispiel aus den Tutorials, sondern der Browser-Pooling-Code, den Sie für die gleichzeitige PDF-Generierung benötigen:

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
$vbLabelText   $csharpLabel

Es handelt sich um ~60 Zeilen Infrastrukturcode, bevor Sie ein einziges PDF erzeugen. Außerdem benötigen Sie eine Überwachung von Speicherlecks (Chromium-Prozesse sammeln mit der Zeit Speicher an), Zustandsprüfungen und ein Dockerfile mit mehr als 20 Chromium-Abhängigkeiten. Die Größe des Docker-Images erhöht sich um 300-400 MB.

Vergleichen Sie dies mit dem entsprechenden Ansatz von IronPDF:

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
$vbLabelText   $csharpLabel

Puppeteer Sharp ist realisierbar, wenn Ihr Team den operativen Aufwand tragen kann. Für Teams, die sich auf ihre Anwendung und nicht auf die Browser-Infrastruktur konzentrieren möchten, übernimmtIronPDFdas gleiche Rendering intern.

Warum kann QuestPDF kein HTML konvertieren?

QuestPDF erscheint in praktisch jeder "HTML to PDF C#"-Diskussion auf Reddit und Stack Overflow. Dies führt zu einem einheitlichen Muster: Entwickler kaufen oder integrieren QuestPDF in der Erwartung, dass es HTML konvertiert, und stellen dann fest, dass es überhaupt kein HTML rendert.

QuestPDF ist eine fließende C#-API für die programmatische Erstellung von Dokumenten. Die Positionierung lautet ausdrücklich "Schluss mit der HTML-zu-PDF-Konvertierung" - sie ersetzt den HTML-Ansatz durch C#-Code. Dies ist eine bewusste Designentscheidung. GitHub-Diskussionen von 2022 bis 2024 zeigen, dass Entwickler dies erst nach Beginn der Implementierung feststellen. Die Betreuer bestätigen immer wieder, dass HTML-Unterstützung nicht geplant ist.

Wenn Ihr bestehender Arbeitsablauf HTML-Vorlagen verwendet - Razor-Ansichten für Rechnungen, Dashboard-HTML für Berichte, Web-Inhalte für die Archivierung - erfordert QuestPDF das Neuschreiben jeder Vorlage in C# fließenden API-Code. Für neue Projekte, bei denen Sie Dokumentenlayouts von Grund auf mit strukturierten Daten erstellen, ist die API von QuestPDF gut konzipiert und produktiv.

Die Community-Lizenz gilt für Unternehmen mit einem jährlichen Bruttoumsatz von weniger als 1 Million US-Dollar. Darüber hinaus ist eine kommerzielle Lizenzierung erforderlich.

Was ist mit Aspose.PDF?

Aspose.PDF bietet umfassende PDF-Funktionen mit kommerzieller Lizenzierung (ab ~$999/Entwickler). Die HTML-Konvertierung verwendet eine benutzerdefinierte Engine, keinen Browser - ähnlich wie iText kann sie zwar grundlegendes HTML verarbeiten, aber moderne CSS-Funktionen nicht korrekt darstellen.

Das Hauptaugenmerk liegt auf der Plattformstabilität: Asposehängt von System.Drawing.Common ab, das unter Linux libgdiplus benötigt. Microsoft hat dies für Nicht-Windows-Plattformen in .NET 6+ abgeschafft. Entwickler berichten von Speicherlecks, die speziell bei Linux-Bereitstellungen auftreten und unter Windows nicht vorkommen. Für reine Windows-Umgebungen ist Asposegeeignet. Bei plattformübergreifenden oder containerisierten Implementierungen stellt die Abhängigkeitskette ein ständiges Risiko dar.

Wie handhabtIronPDFdie HTML-zu-PDF-Konvertierung?

IronPDF bettet Chromium direkt in das NuGet-Paket ein. CSS Flexbox, Grid, benutzerdefinierte Eigenschaften, @font-face, Media-Queries und JavaScript werden alle wie in Chrome ausgeführt. Die Ausgabe stimmt mit dem Browser überein, da dieser die gleiche Rendering-Engine verwendet.

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")
$vbLabelText   $csharpLabel

Dabei wird CSS Grid mit auto-fit/minmax, benutzerdefinierten Eigenschaften, linear-gradient, border-radius und :root Selektoren verwendet. Jede einzelne dieser Funktionen versagt in pdfHTML von iText, bricht in wkhtmltopdf ab und existiert nicht in PdfSharp oder QuestPDF.

Wie kann ich von anderen Bibliotheken migrieren?

Für Teams, die von iTextSharp oder wkhtmltopdf migrieren, akzeptiertIronPDFdirekt URLs - nützlich, wenn Ihr bestehender Workflow HTML-Dateien generiert oder Seiten bereitstellt:

using IronPdf;

var renderer = new ChromePdfRenderer();

// Convert from URL — useful when migrating from wkhtmltopdf URL-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 from wkhtmltopdf URL-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")
$vbLabelText   $csharpLabel

Bereitstellung

IronPDF läuft auf Windows (x64), Linux (x64, ARM64), macOS (x64, Apple Silicon) und Docker-Containern. Die Docker-Konfiguration ist ein Standard-.NET-Image:

FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY . .
ENTRYPOINT ["dotnet", "MyApp.dll"]

Keine Chromium-Installation, keine Abhängigkeiten von nativen Bibliotheken, keine Sandbox-Konfiguration.

Lizenzierung: Unbefristete Lizenzen beginnen bei 749 $. Veröffentlichte Preise unter ironPdf.com. Keine AGPL, keine Gebühren pro Dokument, keine Umsatzschwellen.

Leistungsvergleiche

Getestet auf einer Standard_D4s_v3 Azure VM (4 vCPU, 16GB RAM) mit Ubuntu 22.04 und .NET 8. Testdokument: eine 200-Elemente-HTML-Rechnungsvorlage mit CSS-Grid-Layout, eingebetteten Bildern und einem JavaScript-generierten Diagramm. Jede Messung umfasste im Durchschnitt 50 Iterationen nach einer Aufwärmphase von 5 Iterationen.

Szenario IronPDF Puppeteer Sharp iText pdfHTML wkhtmltopdf
Einfaches HTML (kein JS) ~150ms ~500ms ~200ms ~200ms
Komplexes CSS (Flexbox/Grid) ~250ms ~600ms Unvollständige Ausgabe Unvollständige Ausgabe
Mit JavaScript gerenderter Inhalt ~350ms ~800ms Fails (keine JS-Engine) Misslungen/Teilweise
Speicher pro Vorgang ~80MB ~150MB ~60MB ~50MB
Kaltstart (erste Generation) 2-5s 3-8s <1s <1s

iText und wkhtmltopdf zeigen schnellere Kaltstarts, da sie keine Browser-Engine initialisieren. Dieser Vergleich ist jedoch nur für Szenarien aussagekräftig, in denen alle Bibliotheken eine korrekte Ausgabe liefern - und für komplexe CSS- oder JavaScript-Inhalte liefern nurIronPDFund Puppeteer Sharpbrauchbare Ergebnisse.

Hinweis: Dies sind typische Beobachtungen auf der angegebenen Hardware. Ihre Leistung hängt von der Komplexität von HTML, der Länge des Dokuments und den Serverressourcen ab. Testen Sie mit Ihren tatsächlichen Arbeitslasten, bevor Sie Entscheidungen treffen.

Funktionsvergleich

Feature IronPDF iText 7 Puppeteer Sharp wkhtmltopdf PdfSharp QuestPDF Aspose
HTML zu PDF Ja (Chromium) Begrenzt (CSS 2.1) Ja (Chrome) Veraltet Nein Nein Beschränkt
CSS Flexbox/Grid Ja Nein Ja Nein Nein Nein Nein
JavaScript-Ausführung Ja Nein Ja Beschränkt Nein Nein Nein
Plattformübergreifend (keine libgdiplus) Ja Ja Ja Nicht anwendbar Teilweise Ja Nein
Veröffentlichte Preise $749+ Nein ($15K-$210K/Jahr) Frei (MIT) Kostenlos Frei (MIT) Kostenlos <$1M $999+
Aktive Wartung Ja Ja Ja Aufgegeben Ja Ja Ja

Welche Bibliothek soll ich wählen?

HTML-Vorlagen mit modernem CSS → IronPDF bietet eingebettetes Chromium ohne externe Prozessverwaltung. Wenn Ihr Team die Browser-Infrastruktur verwalten kann, ist Puppeteer Sharpeine brauchbare Alternative.

Programmatische Dokumentenerzeugung aus Daten, kein HTML → QuestPDF bietet eine elegante, fließende API. Erwarten Sie keine HTML-Konvertierung.

Einfache PDF-Bearbeitung (Zusammenführen, Teilen, Wasserzeichen) → PdfSharp ist kostenlos und für Nicht-HTML-Aufgaben geeignet.

Vermeiden Sie für neue Projekte: wkhtmltopdf (aufgegeben, CVEs), iText ohne kommerzielle Lizenz (AGPL-Falle), Asposeauf Linux (Speicherlecks).

Die entscheidende Frage ist, ob Ihr Arbeitsablauf HTML-Vorlagen verwendet. Nur Chromium-basierte Lösungen erzeugen eine korrekte Ausgabe mit modernem CSS. Wenn dies nicht der Fall ist, hängt die Wahl von den API-Präferenzen und den Lizenzbedingungen ab.