IRONSOFTWAREHOME

Iron Suite for .NET

10 bibliotek .NET. Jeden kompletny pakiet dokumentów.

IRONPDF
IRONWORD
IRONXL
IRONPPT
IRONOCR
IRONBARCODE
IRONQR
IRONPRINT
IRONZIP
IRONWEBSCRAPER
PORÓWNANIE

HTML do PDF w C# — Rzeczywistość opcji bibliotek

Curtis Chau
Curtis Chau
Updated: 8 maja 2026

Konwersja HTML do PDF w C# wymaga biblioteki, która faktycznie renderuje HTML – a nie takiej, która analizuje tylko podzbiór znaczników i aproksymuje CSS 2.1. Większość bibliotek polecanych w wątkach na Stack Overflow i dyskusjach na Reddit albo nie potrafi renderować nowoczesnego CSS, albo mają ograniczenia licencyjne dyskwalifikujące ich do użytku komercyjnego, albo zostały porzucone z niezałatanymi lukami bezpieczeństwa.

Ten artykuł porównuje biblioteki, które programiści faktycznie napotykają, szukając "HTML to PDF C#", dokumentuje, co każda z nich może a czego nie może renderować, zawiera testy wydajności z metodologią i pokazuje rzeczywisty koszt operacyjny każdej z metod.

Quickstart: HTML do PDF in C#

using IronPdf;

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1>");
pdf.SaveAs("output.pdf");

Zainstaluj przez NuGet: Install-Package IronPdf. Działa na Windows, Linux, macOS i Docker bez zewnętrznych zależności.

Dlaczego konwersja HTML do PDF jest trudna?

Poprawne renderowanie HTML do PDF wymaga zaimplementowania tych samych pięciu komponentów, co przeglądarka internetowa: parsera HTML, silnika CSS (w tym Flexbox, Grid, kaskadowania, specyficzności i zapytań medialnych), środowiska uruchomieniowego JavaScript, silnika układu i pipeline'u renderowania, który łączy to wszystko do PDF z dokładnością do sub-piksela.

Tradycyjne biblioteki PDF implementują pierwsze dwa komponenty częściowo i całkowicie pomijają JavaScript. Dlatego radzą sobie ze standardowym HTML, ale psują się na wszystkim, co nowoczesna przeglądarka renderuje poprawnie. Jedynym sposobem na dopasowanie się do wyjścia przeglądarki jest użycie silnika przeglądarki.

Które biblioteki faktycznie konwertują HTML do PDF?

Owijacze wkhtmltopdf — ekosystem błędów ładowania DLL

Najczęściej wyszukiwane zapytanie przyciągające programistów do tych artykułów to jakaś wariacja:

System.DllNotFoundException: Nie można załadować DLL 'libwkhtmltox'
Text

Warianty specyficzne dla platformy obejmują:

Nie można załadować biblioteki współdzielonej 'wkhtmltox' lub jednej z jej zależności
    (Linux — libwkhtmltox.so not found)

Nie można odnaleźć określonego modułu. (0x8007007E)
    (Windows — wkhtmltox.dll path not configured)

dyld: Biblioteka nie załadowana: libwkhtmltox.dylib
    (macOS — not supported on ARM64/Apple Silicon)
Text

Te błędy pochodzą z DinkToPdf, NReco.PdfGenerator, WkHtmlToXSharp i innych owijaczy C# wokół tej samej porzuconej binarki. Organizacja wkhtmltopdf na GitHub została zarchiwizowana w lipcu 2024. Podstawowy silnik QtWebKit został zdeprecjonowany przez Qt w 2015 roku. Strona statusu projektu wyraźnie oznacza go jako zdeprecjonowany.

Poza problemami z ładowaniem DLL, silnik renderujący jest zamrożony na poziomie możliwości około Safari 2011. Brak Flexbox, brak Grid, ograniczony CSS3, zawodny JavaScript. I są niezałatane krytyczne luki: CVE-2022-35583(CVSS 9.8) umożliwia ataki SSRF, które mogą wyciekają dane AWS przez spreparowany HTML.

Czas wkhtmltopdf już minął. Błędy ładowania DLL są symptomem głębszego problemu: polegasz na porzuconym oprogramowaniu bez drogi do przodu.

###iText(pdfHTML Add-On) — ograniczone CSS, licencja AGPL

Moduł pdfHTMLiTextkonwertuje HTML do PDF, używając niestandardowego parsera — nie silnika przeglądarki. Obsługuje podstawowy HTML/CSS, ale nie renderuje Flexbox, Grid ani JavaScript.

Tryb awaryjny jest cichy: pdfHTML nie rzuca wyjątków, gdy napotyka nieobsługiwany CSS. Renderuje to, co może, a resztę ignoruje. Pojemnik display: flex z gap: 20px i justify-content: space-between renderuje się jako elementy ustawione pionowo bez odstępów. Programiści odkrywają to po integracji, a nie w trakcie.

Licencjonowanie: AGPL — wymaga udostępnienia kodu źródłowego całej aplikacji dostępnej z sieci, lub zakupu licencji komercyjnej. Ceny nie są opublikowane; dane zewnętrzne sugerują $15,000–$210,000 rocznie.

Jak zużycie pamięci się porównuje?

pdfHTML iTexta ładuje cały dokument do pamięci w celu przetworzenia. Dla typowych dokumentów biznesowych jest to do opanowania, ale duże raporty HTML z osadzonymi obrazami mogą powodować znaczną presję pamięci w porównaniu do podejść strumieniowych.

DlaczegoPDFSharpnie wspiera HTML?

PdfSharp pojawia się w wynikach wyszukiwania "HTML to PDF" ze względu na swoją popularność (34,9 miliona pobrań z NuGet) i częste rekomendacje. Ale PdfSharp nie posiada parsera HTML. Zapewnia bazujące na współrzędnych API do rysowania: DrawString(), DrawRectangle(), DrawImage() z określonymi pozycjami X/Y.

Powszechnie sugerowane obejście, HtmlRenderer.PdfSharp, obsługuje tylko HTML 4.01 i CSS Level 2. Jeśli Twój HTML używa jakiejkolwiek funkcji CSS wprowadzonej po 2010 roku — Flexbox (2012), Grid (2017), właściwości niestandardowe (2017), border-radius (2011) — to nie zostanie wyrenderowany.

Deweloperzy, którzy wybierają PdfSharp oczekując wsparcia dla HTML, kończą na ręcznym pozycjonowaniu każdego elementu z użyciem kodu opartego na współrzędnych lub dodają drugą bibliotekę do renderowania HTML — w tym momencie PdfSharp jest zbędny.

Co sprawia, że Puppeteer jest tak wymagający pod względem zasobów?

Puppeteer Sharp kontroluje Headless Chrome przez powiazania .NET. Dokładność renderowania odpowiada Chrome, ponieważ jest to Chrome. Koszt jest operacyjny: zarządzasz zewnętrznymi procesami przeglądarki.

Oto jak faktycznie wygląda wdrożeniePuppeteer Sharpw środowisku produkcyjnym — nie jest to 5-wierszowy przykład z samouczków, ale kod puli przeglądarek potrzebny do równoczesnego generowania plików PDF:

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();
        }
    }
}

To około 60 wierszy kodu infrastruktury, zanim wygenerujesz pojedynczy plik PDF. Potrzebne jest również monitorowanie wycieków pamięci (procesy Chromium z czasem gromadzą pamięć), kontrole stanu oraz plik Dockerfile z ponad 20 zależnościami Chromium. Rozmiar obrazu Docker wzrasta o 300–400 MB.

Porównaj to z odpowiednim podejściem IronPDF:

using IronPdf;

var renderer = new ChromePdfRenderer();
var pdf = renderer.RenderHtmlAsPdf(html);
// Browser pooling, process management, crash recovery — handled internally

Puppeteer Sharp jest opłacalny, jeśli Twój zespół jest w stanie pokryć związane z nim koszty operacyjne. Dla zespołów, które chcą skupić się na swojej aplikacji, a nie na infrastrukturze przeglądarki,IronPDF obsługuje to samo renderowanie wewnętrznie.

DlaczegoQuestPDFnie może konwertować plików HTML?

QuestPDF pojawia się praktycznie w każdej dyskusji na temat "HTML do PDF w C#" na Reddicie i Stack Overflow. Powstaje w ten sposób spójny schemat: programiści kupują lub integrują QuestPDF, oczekując konwersji do HTML, a następnie odkrywają, że w ogóle nie renderuje on HTML.

QuestPDF to płynnie działający interfejs API w języku C# do programowego tworzenia dokumentów. Jego pozycjonowanie wyraźnie brzmi: "przestań zmagać się z konwersją HTML na PDF" — zastępuje ono podejście oparte na HTML kodem C#. Jest to świadomy wybór projektowy. Dyskusje na GitHubie z lat 2022–2024 pokazują, że programiści odkrywają to po rozpoczęciu wdrażania. Twórcy konsekwentnie potwierdzają, że obsługa HTML nie jest planowana.

Jeśli obecny proces wykorzystuje szablony HTML — widoki Razor dla faktur, kod HTML pulpitu nawigacyjnego dla raportów, treści internetowe do archiwizacji —QuestPDFwymaga przepisania każdego szablonu w płynnym kodzie API języka C#. W przypadku nowych projektów, w których tworzysz układy dokumentów od podstaw przy użyciu danych strukturalnych, APIQuestPDFjest dobrze zaprojektowane i wydajne.

Licencja społecznościowa obejmuje firmy o rocznych przychodach brutto poniżej 1 mln USD. Ponadto wymagana jest licencja komercyjna.

A co z Aspose.PDF?

Aspose.PDF zapewnia szeroki zakres funkcji związanych z plikami PDF w ramach licencji komercyjnej (ceny zaczynają się od ~999 USD/programista). Konwersja HTML wykorzystuje niestandardowy silnik, a nie przeglądarkę — podobnie jak iText, obsługuje podstawowy HTML, ale nie renderuje poprawnie nowoczesnych funkcji CSS.

Głównym problemem jest stabilność platformy:Asposeopiera się na System.Drawing.Common, co wymaga libgdiplus w systemie Linux. W .NET 6+ firma Microsoft wycofała tę funkcję dla platform innych niż Windows. Programiści zgłaszają wycieki pamięci charakterystyczne dla wdrożeń w systemie Linux, które nie występują w systemie Windows. W środowiskach wyłącznie dla systemu Windows sprawdzi się Aspose. W przypadku wdrożeń wielopłatformowych lub kontenerowych łańcuch zależności stwarza ciągłe ryzyko.

W jaki sposób IronPDF obsługuje konwersję HTML do PDF?

IronPDF osadza Chromium bezpośrednio w pakiecie NuGet. CSS Flexbox, Grid, właściwości niestandardowe, @font-face, zapytania medialne i JavaScript działają tak samo jak w Chrome. Wynik jest zgodny z przeglądarką, ponieważ wykorzystuje ten sam silnik renderujący.

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");

To wykorzystuje CSS Grid z minmax, właściwościami niestandardowymi, linear-gradient, border-radius i selektorami :root. Każda z tych funkcji zawodzi w pdfHTML od iText, psuje się w wkhtmltopdf i nie istnieje w PdfSharp lub QuestPDF.

Jak przeprowadzić migrację z innych bibliotek?

Dla zespolow migrujacych ziTextlub wkhtmltopdf,IronPDF akceptuje URL-e bezposrednio — przydatne, gdy istniejacy proces generuje pliki HTML lub serwuje strony:

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");

Wdrożenie

IronPDF działa na systemach Windows (x64), Linux (x64, ARM64), macOS (x64, Apple Silicon) oraz w kontenerach Docker. Konfiguracja Docker to standardowy obraz .NET Standard:

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

Bez instalacji Chromium, bez zależności od bibliotek natywnych, bez konfiguracji piaskownicy.

Licencjonowanie: Licencje wieczyste zaczynają się od $liteLicense. Ceny opublikowane na stronie ironpdf.com. Bez licencji AGPL, bez opłat za dokument, bez progów przychodów.

Testy wydajności

Przetestowano na maszynie wirtualnej Azure Standard_D4s_v3 (4 vCPU, 16 GB pamięci RAM) z systemem Ubuntu 22.04 i platformą .NET 8. Dokument testowy: 200-elementowy szablon faktury HTML z układem CSS Grid, osadzonymi obrazami i wykresem wygenerowanym przez JavaScript. Każdy pomiar jest średnią z 50 iteracji po 5-iteracyjnym okresie rozgrzewki.

ScenariuszIronPDFPuppeteer SharpiText pdfHTMLwkhtmltopdf
Prosty HTML (bez JS)~150ms~500 ms~200 ms~200 ms
Złożone CSS (Flexbox/Grid)~250ms~600 msUszkodzony wynikUszkodzony wynik
Treści renderowane w JavaScript~350ms~800msBłędy (brak silnika JS)Nie powiodlo sie/Czesciowe
Pamieć na operacje~80 MB~150 MB~60MB~50MB
Zimny start (pierwsza generacja)2–5s3–8s<1s<1s

iText i wkhtmltopdf charakteryzują się szybszym uruchamianiem, ponieważ nie inicjują silnika przeglądarki. Jednak porównanie to ma znaczenie tylko w scenariuszach, w których wszystkie biblioteki generują poprawny wynik — a w przypadku złożonej zawartości CSS lub JavaScript tylko IronPDF iPuppeteer Sharpzapewniają użyteczne wyniki.

Uwaga: Są to typowe obserwacje dotyczące określonego sprzętu. Wydajność będzie zależała od złożoności kodu HTML, długości dokumentu oraz zasobów serwera. Przed podjęciem decyzji przetestuj rozwiązanie na rzeczywistych obciążeniach.

Porównanie funkcji

FunkcjaIronPDFiTextPuppeteer SharpwkhtmltopdfPDFSharpQuestPDFAspose
HTML do PDFTak (Chromium)Ograniczony (CSS 2.1)Tak (Chrome)PrzestarzalyNieNieOgraniczone
CSS Flexbox/GridTakNieTakNieNieNieNie
Wykonanie kodu JavaScriptTakNieTakOgraniczoneNieNieNie
Wielopłatformowe (bez libgdiplus)TakTakTakNie dotyczyCzęścioweTakNie
Opublikowane ceny$liteLicense+Nie (od $15K–$210K/rok)Bezpłatne (MIT)BezpłatneBezpłatne (MIT)Bezpłatne <$1M$999+
Aktywna konserwacjaTakTakTakPorzuconyTakTakTak

Którą bibliotekę wybrać?

Szablony HTML z nowoczesnym CSS → IronPDF zapewnia wbudowany Chromium bez zewnętrznego zarządzania procesami. Jeśli Twój zespół potrafi zarządzać infrastrukturą przeglądarek,Puppeteer Sharpjest realną alternatywą.

Programowe generowanie dokumentów na podstawie danych, bez HTML → QuestPDF oferuje elegancki, płynny interfejs API. Nie wybieraj tego, oczekując konwersji HTML.

Prosta manipulacja PDF (laczenie, dzielenie, znak wodny) → PDFSharp jest darmowy i zdolny do zadan niezaleznych od HTML.

Unikaj w nowych projektach: wkhtmltopdf (porzucony, CVE),iTextbez licencji komercyjnej (pułapka AGPL),Asposena Linuksie (wycieki pamięci).

Kluczowe pytanie brzmi: czy w Twoim procesie pracy wykorzystujesz szablony HTML? W takim przypadku tylko rozwiązania oparte na Chromium generują poprawny wynik przy użyciu nowoczesnego CSS. Jeśli tak nie jest, wybór zależy od preferencji dotyczących API i ograniczeń licencyjnych.

Zwróć uwagę: Aspose, DinkToPdf, NReco, PDFSharp, PuppeteerSharp, QuestPDF,iTexti wkhtmltopdf są zarejestrowanymi znakami towarowymi ich właścicieli. Ta strona nie jest zwiazana, rekomendowana ani sponsorowana przezAsposePty Ltd, CodeFlint, DinkToPdf, NReco, PuppeteerSharp, empira Software GmbH,iTextGroup lub wkhtmltopdf. Wszystkie nazwy produktów, logo i marki są własnością ich odpowiednich właścicieli. Porównania mają charakter wyłącznie informacyjny i odzwierciedlają informacje dostępne publicznie w momencie pisania.
Key in blue circle

Uzyskaj natychmiast swój darmowy 30-dniowy Klucz Testowy.

Your trial license will be sent to your email address

Brak ograniczeń. 100% dostępności. Bez karty kredytowej.

bullet_checkedNie wymaga karty kredytowej ani tworzenia kontaBrak ograniczeń. 100% dostępności. Bez karty kredytowej.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
Otrzymaj swoją Konsultację Bez Zobowiązań
Wypełnij poniższy formularz lub wyślij e-mail na sales@ironsoftware.com
Twoje dane zawsze będą utrzymywane w tajemnicy.
Zaufane przez miliony inżynierów na całym świecie
Logotypy klientów Iron Software
Otrzymaj swój darmowy Klucz Próbny na 30 dni natychmiast.
Nie wymaga karty kredytowej ani tworzenia konta