Passer au contenu du pied de page
OUTILS PDF

Découvrez le meilleur logiciel de rédaction de PDF pour 2025

Choisir une bibliothèque C# pour convertir HTML en PDF en 2026 revient à une décision : quel moteur de rendu convient aux documents que vous produisez réellement. Sur .NET 10, le champ se divise en trois groupes. Les moteurs basés sur les navigateurs (Chromium via PuppeteerSharp, Auteurou une version intégrée) rendent CSS moderne et JavaScriptavec précision. Les bibliothèques programmatiques (iText, PdfSharp) dessinent des PDFs à partir de parseurs personnalisés et échangent la fidélité du web moderne pour une empreinte minuscule. Les outils de mise en page orientés code (QuestPDF) ignorent entièrement HTML. Cette comparaison passe en revue toutes les options avec du code C# fonctionnel, une grille d'évaluation, des benchmarks originaux, et les conditions de licence qui déterminent ce que vous pouvez diffuser.

TL;DR : la réponse rapide et le code de travail le plus rapide

Pour un rendu précis du CSS moderne et de JavaScript, utilisez un moteur de niveau navigateur. La voie gratuite estPuppeteerSharpou Playwright, qui fournissent un rendu du niveau de Chrome mais vous obligent à gérer un processus de navigateur séparé et un binaire volumineux. La voie commerciale intègre Chromium dans le package, ne laissant rien à installer ou à lancer séparément. Pour des documents statiques simples, une bibliothèque légère telle que PdfSharp suffit. Pour des mises en page définies par code sans source HTML, QuestPDF est le chemin le plus court.

La voie de travail la plus rapide vers un PDF utilisant un moteur intégré est un appel de rendu unique :

using IronPdf;

// The embedded Chromium engine ships inside the package, so no browser is launched or downloaded
var renderer = new ChromePdfRenderer();
// One synchronous call parses the HTML string and produces an in-memory PDF document
var pdf = renderer.RenderHtmlAsPdf("<h1>Invoice</h1><p>Generated from HTML.</p>");
// Write the rendered document to disk
pdf.SaveAs("output.pdf");
using IronPdf;

// The embedded Chromium engine ships inside the package, so no browser is launched or downloaded
var renderer = new ChromePdfRenderer();
// One synchronous call parses the HTML string and produces an in-memory PDF document
var pdf = renderer.RenderHtmlAsPdf("<h1>Invoice</h1><p>Generated from HTML.</p>");
// Write the rendered document to disk
pdf.SaveAs("output.pdf");
Imports IronPdf

' The embedded Chromium engine ships inside the package, so no browser is launched or downloaded
Dim renderer As New ChromePdfRenderer()
' One synchronous call parses the HTML string and produces an in-memory PDF document
Dim pdf = renderer.RenderHtmlAsPdf("<h1>Invoice</h1><p>Generated from HTML.</p>")
' Write the rendered document to disk
pdf.SaveAs("output.pdf")
$vbLabelText   $csharpLabel

La comparaison complète, les benchmarks et les détails de licence suivent ci-dessous.

Tableau de recommandation rapide par scénario

Faites correspondre votre contrainte à un choix avant de lire l'analyse approfondie.

Si vous avez besoin Choix recommandé Pourquoi
CSS moderne, Flexbox, Grid, polices web à grande échelle IronPDF (Chromium intégré) Rendu précis, rendus à chaud rapides, aucun navigateur externe à déployer
Rendu de niveau navigateur gratuit, disposé à gérer les opérations PuppeteerSharp ou Playwright Chromium réel, licence MIT, empreinte de déploiement plus lourde
HTML statique simple, pas de JavaScript PdfSharp avec HtmlRenderer Léger, gratuit, limité au CSS hérité
Mises en page fixes programmatiques, pas de source HTML QuestPDF API C# fluide, très rapide, pas un moteur de rendu HTML
Zéro infrastructure, traitement hébergé Une API de conversion HTML en PDF Aucun moteur de rendu à maintenir dans votre application
Projet hérité sur wkhtmltopdf Migrer vers un moteur Chromium wkhtmltopdf est archivé, échoue sur le CSS actuel et comporte une CVE SSRF critique

Qu'est-ce qui rend HTML en PDF difficile en C

Les navigateurs rendent le contenu fluide pour les écrans ; PDF exige des pages fixes, des dimensions exactes et une pagination stricte. L'écart entre ces deux modèles est là où les bibliothèques réussissent ou échouent. Cinq critères les séparent, et ils s'appliquent à chaque outil, quel que soit le fournisseur.

  1. Moteur de rendu et CSS moderne : le moteur qui analyse HTML et CSS est le principal différenciateur. Les modèles actuels s'appuient sur Flexbox pour l'alignement, Grid pour la mise en page bidimensionnelle, @font-face pour la typographie, et SVG pour les actifs vectoriels. Les moteurs basés sur les forks WebKit anciens ou les parseurs personnalisés ont tendance à échouer tranquillement sur ces points et à effondrer les mises en page stylées en une pile verticale. La gestion correcte des règles @media print est tout aussi importante lorsqu'il s'agit de transformer une mise en page d'écran en papier.

  2. Exécution JavaScriptet attentes de rendu : une grande partie du contenu actuel est construite côté client. Les bibliothèques de graphiques comme Chart.js et les frameworks monopages comme Blazor WebAssembly construisent le DOM avec JavaScriptavant que la page ne soit complète. Une bibliothèque sans moteur JavaScriptproduit des graphiques vides ou des pages partiellement chargées, ce qui rend la capacité à exécuter des scripts et attendre un signal prêt au rendu décisive pour les documents dynamiques.

  3. Poids du déploiement et démarrage à froid : les outils qui pilotent un navigateur sans tête externe téléchargent des centaines de mégaoctets de binaires, gonflant les images de conteneur et ralentissant les démarrages à froid. Dans des environnements sans serveur tels qu'AWS Lambda ou Azure Functions, où le stockage et la mémoire sont limités, le poids du conteneur peut déterminer si une bibliothèque est viable ou non.

  4. Licence et sa portée légale : une licence dicte plus que le coût. Le champ PDF .NET couvre des termes permissifs (MIT, Apache 2.0), des termes copyleft (AGPLv3) qui peuvent exiger de divulguer votre source pour les applications orientées réseau, des niveaux communautaires verrouillés par revenu, et des licences commerciales perpétuelles. Le mauvais choix peut créer une obligation qui ne se révèle qu'au moment d'un audit.

  5. Performance et mémoire à grande échelle : une bibliothèque qui est convenable dans un test console peut se figer sous une API web concurrente. Certaines diffusent le travail ; d'autres chargent le document entier en mémoire d'un coup et déclenchent des pauses de collecte des ordures pendant les travaux par lots. Le démarrage à froid, le rendu à chaud et la mémoire par rendu sont trois mesures distinctes qui nécessitent chacune une attention.

Les bibliothèques, chacune avec du code fonctionnel

Les options gratuites et open-source viennent en premier. Chaque extrait ci-dessous a été compilé et exécuté sur .NET 10, et les moteurs Chromium montrent à la fois l'entrée de chaîne HTML et de URL puisqu'ils les prennent tous deux en charge.

PuppeteerSharp

PuppeteerSharp est un portage .NET de Puppeteer Node.js de Google, sorti pour la première fois en 2017. Il pilote une instance Chromium sans tête via le protocole Chrome DevTools. C'est un orchestrateur de processus plutôt qu'une bibliothèque in-process : l'application télécharge une version de Chromium avec BrowserFetcher, lance le navigateur, définit le contenu de la page et capture le PDF.

using PuppeteerSharp;
using System.Threading.Tasks;

public class PuppeteerExample
{
    public async Task GeneratePdfAsync()
    {
        // Download a matching Chromium build if it is not already present (the 100-300 MB fetch)
        await new BrowserFetcher().DownloadAsync();

        // Start a headless browser process; await using disposes it to avoid orphaned processes
        await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });
        // Open a fresh tab to work in
        await using var page = await browser.NewPageAsync();

        // Load the HTML directly into the page instead of navigating to a URL
        await page.SetContentAsync("<h1>Invoice Report</h1><p>Rendered with PuppeteerSharp.</p>");
        // Drive Chrome's print pipeline to emit the PDF file
        await page.PdfAsync("puppeteer_output.pdf");
    }
}
using PuppeteerSharp;
using System.Threading.Tasks;

public class PuppeteerExample
{
    public async Task GeneratePdfAsync()
    {
        // Download a matching Chromium build if it is not already present (the 100-300 MB fetch)
        await new BrowserFetcher().DownloadAsync();

        // Start a headless browser process; await using disposes it to avoid orphaned processes
        await using var browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true });
        // Open a fresh tab to work in
        await using var page = await browser.NewPageAsync();

        // Load the HTML directly into the page instead of navigating to a URL
        await page.SetContentAsync("<h1>Invoice Report</h1><p>Rendered with PuppeteerSharp.</p>");
        // Drive Chrome's print pipeline to emit the PDF file
        await page.PdfAsync("puppeteer_output.pdf");
    }
}
Imports PuppeteerSharp
Imports System.Threading.Tasks

Public Class PuppeteerExample
    Public Async Function GeneratePdfAsync() As Task
        ' Download a matching Chromium build if it is not already present (the 100-300 MB fetch)
        Await New BrowserFetcher().DownloadAsync()

        ' Start a headless browser process; using disposes it to avoid orphaned processes
        Using browser = Await Puppeteer.LaunchAsync(New LaunchOptions With {.Headless = True})
            ' Open a fresh tab to work in
            Using page = Await browser.NewPageAsync()
                ' Load the HTML directly into the page instead of navigating to a URL
                Await page.SetContentAsync("<h1>Invoice Report</h1><p>Rendered with PuppeteerSharp.</p>")
                ' Drive Chrome's print pipeline to emit the PDF file
                Await page.PdfAsync("puppeteer_output.pdf")
            End Using
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

Pour capturer une URL en direct au lieu d'une chaîne, naviguez vers celle-ci avant l'appel :

// Navigate the tab to a live URL so the loaded page becomes the render source
await page.GoToAsync("https://example.com");
// Capture whatever is currently displayed as a PDF
await page.PdfAsync("from_url.pdf");
// Navigate the tab to a live URL so the loaded page becomes the render source
await page.GoToAsync("https://example.com");
// Capture whatever is currently displayed as a PDF
await page.PdfAsync("from_url.pdf");
Imports System.Threading.Tasks

' Navigate the tab to a live URL so the loaded page becomes the render source
Await page.GoToAsync("https://example.com")
' Capture whatever is currently displayed as a PDF
Await page.PdfAsync("from_url.pdf")
$vbLabelText   $csharpLabel

Forces :

  • Le rendu correspond à Google Chrome, avec un support complet de Flexbox, Grid et des polices web.
  • Exécute JavaScriptet peut attendre le réseau-idle avant la capture.
  • Sous licence MIT, donc l'utilisation commerciale n'entraîne aucune obligation copyleft.

Limitations :

  • Un premier lancement télécharge une version de Chromium de 100 Mo à 300 Mo.
  • Chaque instance de navigateur consomme une quantité de mémoire importante, donc les lots concurrents nécessitent une piscine de navigateurs.
  • Aucun PDF/A ou PDF/UA intégré.

License: MIT. Optez pour cela lorsque vous souhaitez une sortie gratuite de fidélité Chrome et que l'équipe peut absorber la surcharge des opérations. Pour une comparaison directe sur ce compromis, voir la comparaisonPuppeteerSharpvs IronPDF.

Auteurfor .NET

Playwright est maintenu par Microsoft comme un framework d'automatisation multi-navigateurs pour Chromium, WebKit et Firefox. Les équipes le réutilisent pour HTML en PDF via Page.PdfAsync, bien que la génération de PDF ne fonctionne qu'avec Chromium. La configuration récupère des binaires de navigateur grâce à une étape d'installation unique.

using Microsoft.Playwright;
using System.Threading.Tasks;

public class PlaywrightExample
{
    public async Task GeneratePdfAsync()
    {
        // Create the Auteurdriver that manages the installed browser binaries
        using var playwright = await Playwright.CreateAsync();
        // PDF output is Chromium-only, so launch the Chromium build specifically
        await using var browser = await playwright.Chromium.LaunchAsync();
        // Open a new page (tab) to render into
        var page = await browser.NewPageAsync();

        // Set the HTML content in place rather than navigating to a URL
        await page.SetContentAsync("<html><body><h1>Sales Dashboard</h1></body></html>");
        // Emit the PDF with an explicit A4 page format
        await page.PdfAsync(new PagePdfOptions { Path = "playwright_output.pdf", Format = "A4" });
    }
}
using Microsoft.Playwright;
using System.Threading.Tasks;

public class PlaywrightExample
{
    public async Task GeneratePdfAsync()
    {
        // Create the Auteurdriver that manages the installed browser binaries
        using var playwright = await Playwright.CreateAsync();
        // PDF output is Chromium-only, so launch the Chromium build specifically
        await using var browser = await playwright.Chromium.LaunchAsync();
        // Open a new page (tab) to render into
        var page = await browser.NewPageAsync();

        // Set the HTML content in place rather than navigating to a URL
        await page.SetContentAsync("<html><body><h1>Sales Dashboard</h1></body></html>");
        // Emit the PDF with an explicit A4 page format
        await page.PdfAsync(new PagePdfOptions { Path = "playwright_output.pdf", Format = "A4" });
    }
}
Imports Microsoft.Playwright
Imports System.Threading.Tasks

Public Class PlaywrightExample
    Public Async Function GeneratePdfAsync() As Task
        ' Create the Auteurdriver that manages the installed browser binaries
        Using playwright = Await Playwright.CreateAsync()
            ' PDF output is Chromium-only, so launch the Chromium build specifically
            Await Using browser = Await playwright.Chromium.LaunchAsync()
                ' Open a new page (tab) to render into
                Dim page = Await browser.NewPageAsync()

                ' Set the HTML content in place rather than navigating to a URL
                Await page.SetContentAsync("<html><body><h1>Sales Dashboard</h1></body></html>")
                ' Emit the PDF with an explicit A4 page format
                Await page.PdfAsync(New PagePdfOptions With {.Path = "playwright_output.pdf", .Format = "A4"})
            End Using
        End Using
    End Function
End Class
$vbLabelText   $csharpLabel

Avant la première exécution, installez le navigateur avec pwsh bin/Debug/net10.0/playwright.ps1 install chromium (ou appelez le point d'entrée d'installation équivalent dans le code).

Pour une URL en direct, naviguez d'abord vers la page :

// Load a live URL so its rendered DOM becomes the PDF source
await page.GotoAsync("https://example.com");
// Export the loaded page as an A4 PDF
await page.PdfAsync(new PagePdfOptions { Path = "from_url.pdf", Format = "A4" });
// Load a live URL so its rendered DOM becomes the PDF source
await page.GotoAsync("https://example.com");
// Export the loaded page as an A4 PDF
await page.PdfAsync(new PagePdfOptions { Path = "from_url.pdf", Format = "A4" });
Imports System.Threading.Tasks

' Load a live URL so its rendered DOM becomes the PDF source
Await page.GotoAsync("https://example.com")
' Export the loaded page as an A4 PDF
Await page.PdfAsync(New PagePdfOptions With {.Path = "from_url.pdf", .Format = "A4"})
$vbLabelText   $csharpLabel

Où il excelle :

  • Soutenu par Microsoft avec un cycle de sortie actif.
  • Faible latence de premier rendu une fois le navigateur prêt.
  • Rend avec précision les normes web modernes et le JavaScriptcôté client.

Le hic :

  • Même empreinte binaire lourde et gestion du navigateur que PuppeteerSharp.
  • La mémoire monte sans gestion soigneuse du contexte du navigateur.
  • La sortie PDF est une caractéristique secondaire du pipeline d'impression de Chrome, donc elle manque de fonctionnalités de manipulation des documents.

License: MIT. Idéal quand un projet utilise déjà Auteurpour les tests et souhaite un rendu libre à côté.

wkhtmltopdf (via DinkToPdf)

Depuis plus d'une décennie, wkhtmltopdf était l'outil HTML en PDF par défaut. Sous .NET, il est généralement consommé via DinkToPdf, un wrapper C# autour de la bibliothèque native libwkhtmltox. L'API du wrapper est propre, mais le moteur sous-jacent est le problème.

using DinkToPdf;

public class DinkToPdfExample
{
    public void GeneratePdf()
    {
        // SynchronizedConverter serializes calls into the non-thread-safe native libwkhtmltox library
        var converter = new SynchronizedConverter(new PdfTools());

        // Describe the document: global page settings plus one or more HTML content objects
        var doc = new HtmlToPdfDocument
        {
            // Set the paper size and the output file path for the whole document
            GlobalSettings = { PaperSize = PaperKind.A4, Out = "legacy_output.pdf" },
            // Each object is a chunk of HTML to render into the PDF
            Objects = { new ObjectSettings { HtmlContent = "<h1>Legacy Report</h1>" } }
        };

        // Hand the descriptor to the native engine, which writes the file defined in Out
        converter.Convert(doc);
    }
}
using DinkToPdf;

public class DinkToPdfExample
{
    public void GeneratePdf()
    {
        // SynchronizedConverter serializes calls into the non-thread-safe native libwkhtmltox library
        var converter = new SynchronizedConverter(new PdfTools());

        // Describe the document: global page settings plus one or more HTML content objects
        var doc = new HtmlToPdfDocument
        {
            // Set the paper size and the output file path for the whole document
            GlobalSettings = { PaperSize = PaperKind.A4, Out = "legacy_output.pdf" },
            // Each object is a chunk of HTML to render into the PDF
            Objects = { new ObjectSettings { HtmlContent = "<h1>Legacy Report</h1>" } }
        };

        // Hand the descriptor to the native engine, which writes the file defined in Out
        converter.Convert(doc);
    }
}
Imports DinkToPdf

Public Class DinkToPdfExample
    Public Sub GeneratePdf()
        ' SynchronizedConverter serializes calls into the non-thread-safe native libwkhtmltox library
        Dim converter = New SynchronizedConverter(New PdfTools())

        ' Describe the document: global page settings plus one or more HTML content objects
        Dim doc = New HtmlToPdfDocument With {
            ' Set the paper size and the output file path for the whole document
            .GlobalSettings = New GlobalSettings With {.PaperSize = PaperKind.A4, .Out = "legacy_output.pdf"},
            ' Each object is a chunk of HTML to render into the PDF
            .Objects = {New ObjectSettings With {.HtmlContent = "<h1>Legacy Report</h1>"}}
        }

        ' Hand the descriptor to the native engine, which writes the file defined in Out
        converter.Convert(doc)
    End Sub
End Class
$vbLabelText   $csharpLabel

Ce code compile, mais le faire tourner sur une machine propre renvoie System.DllNotFoundException: Unable to load DLL 'libwkhtmltox' jusqu'à ce que les binaires natifs soient copiés dans le répertoire de sortie. Cette étape de dépendance native est le premier signe de la friction de déploiement que ce moteur apporte.

Avantage :

  • Démarrage à froid rapide, sans navigateur moderne à initialiser.
  • Faible mémoire, environ 50 Mo par rendu.

Inconvénients :

  • Le moteur QtWebKit qu'il expédie (une version instantanée de WebKit environ 2012-2013, que Qt a lui-même dépréciée en 2015 et supprimée en 2016) ne peut pas rendre Flexbox, Grid ou le JavaScriptmoderne.
  • Le dépôt wkhtmltopdf a été archivé le 2 janvier 2023 et la dernière version, 0.12.6, date de juin 2020.
  • Il transporte CVE-2022-35583, une faille SSRF (Server-Side Request Forgery) notée CVSS 9.8 (critique) qui n'est pas corrigée car le projet n'est plus maintenu.

Licence : DinkToPdf lui-même est sous MIT, mais il lie les binaires wkhtmltopdf sous LGPLv3, donc l'obligation effective vient de wkhtmltopdf. Adapté aux flux de travail hérités en attente de migration, avec le risque de sécurité gardé à l'esprit. Consultez la comparaison wkhtmltopdf vs IronPDF pour une vue d'ensemble complète de la migration.

PdfSharp and HtmlRenderer

PdfSharp est une bibliothèque open-source largement utilisée, mais une idée fausse courante est qu'elle convertit HTML seule. Elle ne le fait pas. PdfSharp fournit une API de dessin au niveau bas, basée sur les coordonnées. Pour convertir HTML, vous l'associez avec le pont communautaire HtmlRenderer.PdfSharp, qui analyse HTML et émet des commandes de dessin PdfSharp.

using PdfSharp;
using TheArtOfDev.HtmlRenderer.PdfSharp;

public class PdfSharpExample
{
    public void GeneratePdf()
    {
        string html = "<h1>Simple Title</h1><p>Statically rendered text.</p>";

        // The HtmlRenderer bridge parses the HTML and emits PdfSharp drawing commands onto an A4 page
        var pdf = PdfGenerator.GeneratePdf(html, PageSize.A4);
        // Persist the resulting PdfSharp document to disk
        pdf.Save("simple_document.pdf");
    }
}
using PdfSharp;
using TheArtOfDev.HtmlRenderer.PdfSharp;

public class PdfSharpExample
{
    public void GeneratePdf()
    {
        string html = "<h1>Simple Title</h1><p>Statically rendered text.</p>";

        // The HtmlRenderer bridge parses the HTML and emits PdfSharp drawing commands onto an A4 page
        var pdf = PdfGenerator.GeneratePdf(html, PageSize.A4);
        // Persist the resulting PdfSharp document to disk
        pdf.Save("simple_document.pdf");
    }
}
Imports PdfSharp
Imports TheArtOfDev.HtmlRenderer.PdfSharp

Public Class PdfSharpExample
    Public Sub GeneratePdf()
        Dim html As String = "<h1>Simple Title</h1><p>Statically rendered text.</p>"

        ' The HtmlRenderer bridge parses the HTML and emits PdfSharp drawing commands onto an A4 page
        Dim pdf = PdfGenerator.GeneratePdf(html, PageSize.A4)
        ' Persist the resulting PdfSharp document to disk
        pdf.Save("simple_document.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

Deux détails de configuration importent sous .NET 10. Le pont attend la page de code Windows-1252, absente par défaut sur .NET moderne, alors enregistrez-la une fois au démarrage avec Encoding.RegisterProvider(CodePagesEncodingProvider.Instance). Associer le pont avec un package PdfSharp 6.x plus récent casse également à l'exécution avec un MissingMethodException, donc laissez HtmlRenderer tirer sa propre version compatible de PdfSharp plutôt que d'attacher le dernier.

Ça fonctionne :

  • Licence MIT véritablement permissive sans limites de revenu.
  • Léger, sans binaires natifs ni téléchargeurs de navigateur.
  • Pur C#, donc le déploiement sur plusieurs systèmes d'exploitation est simple.

Ce qui casse :

  • Le pont HTML est limité à peu près à HTML 4.01 et CSS Niveau 2, et il a vu un ensemble unique de versions fin 2025 après neuf ans de dormance.
  • Aucune exécution JavaScriptdu tout.
  • Les règles d'impression comme page-break-inside: avoid ne sont pas supportées, donc les lignes de table se divisent sur plusieurs pages.

License: PdfSharp MIT, HtmlRenderer BSD-3-Clause. Le bon choix pour des documents statiques simples sans mise en page complexe. Pour une analyse fonction-par-fonction, voir la comparaison PdfSharp vs IronPDF.

QuestPDF

QuestPDF prend une direction différente : il supprime HTML et définit les mises en page en C# via une API fluide. Pour les données qui proviennent d'objets plutôt que de balisage, cela supprime l'étape de génération HTML uniquement pour le réanalyser.

using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;

public class QuestPdfExample
{
    public void GeneratePdf()
    {
        // The revenue-gated license tier must be declared before any document is built
        QuestPDF.Settings.License = LicenseType.Community;

        // Compose the layout in C# through the fluent API; no HTML anywhere
        var document = Document.Create(container =>
        {
            container.Page(page =>
            {
                // Define the physical page size and margins
                page.Size(PageSizes.A4);
                page.Margin(2, Unit.Centimetre);
                // Place content into named page regions (header and body)
                page.Header().Text("Programmatic Invoice").FontSize(24);
                page.Content().Text("This document is generated without HTML.");
            });
        });

        // Run the layout engine and write the composed document to a file
        document.GeneratePdf("fluent_layout.pdf");
    }
}
using QuestPDF.Fluent;
using QuestPDF.Helpers;
using QuestPDF.Infrastructure;

public class QuestPdfExample
{
    public void GeneratePdf()
    {
        // The revenue-gated license tier must be declared before any document is built
        QuestPDF.Settings.License = LicenseType.Community;

        // Compose the layout in C# through the fluent API; no HTML anywhere
        var document = Document.Create(container =>
        {
            container.Page(page =>
            {
                // Define the physical page size and margins
                page.Size(PageSizes.A4);
                page.Margin(2, Unit.Centimetre);
                // Place content into named page regions (header and body)
                page.Header().Text("Programmatic Invoice").FontSize(24);
                page.Content().Text("This document is generated without HTML.");
            });
        });

        // Run the layout engine and write the composed document to a file
        document.GeneratePdf("fluent_layout.pdf");
    }
}
Imports QuestPDF.Fluent
Imports QuestPDF.Helpers
Imports QuestPDF.Infrastructure

Public Class QuestPdfExample
    Public Sub GeneratePdf()
        ' The revenue-gated license tier must be declared before any document is built
        QuestPDF.Settings.License = LicenseType.Community

        ' Compose the layout in VB.NET through the fluent API; no HTML anywhere
        Dim document = Document.Create(Sub(container)
                                           container.Page(Sub(page)
                                                              ' Define the physical page size and margins
                                                              page.Size(PageSizes.A4)
                                                              page.Margin(2, Unit.Centimetre)
                                                              ' Place content into named page regions (header and body)
                                                              page.Header().Text("Programmatic Invoice").FontSize(24)
                                                              page.Content().Text("This document is generated without HTML.")
                                                          End Sub)
                                       End Sub)

        ' Run the layout engine and write the composed document to a file
        document.GeneratePdf("fluent_layout.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

Points forts :

  • Très rapide, car il évite l'analyse du DOM et la mise en page du navigateur.
  • Mémoire prévisible, linéaire, qui convient aux travaux par lots à haut débit.
  • Une application compagnon offre un aperçu en direct et une recharge à chaud pendant la conception.

Points faibles :

  • C'est un moteur de mise en page, pas un moteur de rendu HTML, il ne peut donc pas convertir une URL ou un modèle HTML existant.
  • Les documents HTML ou Razor existants auraient besoin d'une réécriture complète dans l'API fluide.
  • La licence est passée d'un modèle MIT à un modèle à seuil de revenu.

Licence : Licence communautaire (gratuite pour les entreprises dont le revenu annuel est inférieur à 1 000 000 USD) ou un niveau Professionnel et Enterprise payant. Adapté aux documents à mise en page fixe définis par code, pilotés par des données structurées. Voir la comparaison QuestPDF vs IronPDF pour l'arbitrage entre HTML et mise en page fluide.

iText (pdfHTML)

iText 7 et 8 sont reconnus pour la manipulation programmatique des PDF, et le module complémentaire pdfHTML convertit HTML. Contrairement aux outils Chromium, pdfHTML utilise un parseur personnalisé qui mappe les balises HTML aux objets iText au lieu d'exécuter un navigateur.

using iText.Html2pdf;
using System.IO;

public class iTextExample
{
    public void GeneratePdf()
    {
        string html = "<h1>Report</h1><p>Converted with pdfHTML.</p>";

        // Open the destination stream; using ensures the file handle is released after writing
        using var dest = File.Create("output.pdf");
        // pdfHTML maps the HTML tags to iText objects and writes them to the stream (no browser involved)
        HtmlConverter.ConvertToPdf(html, dest);
    }
}
using iText.Html2pdf;
using System.IO;

public class iTextExample
{
    public void GeneratePdf()
    {
        string html = "<h1>Report</h1><p>Converted with pdfHTML.</p>";

        // Open the destination stream; using ensures the file handle is released after writing
        using var dest = File.Create("output.pdf");
        // pdfHTML maps the HTML tags to iText objects and writes them to the stream (no browser involved)
        HtmlConverter.ConvertToPdf(html, dest);
    }
}
Imports iText.Html2pdf
Imports System.IO

Public Class iTextExample
    Public Sub GeneratePdf()
        Dim html As String = "<h1>Report</h1><p>Converted with pdfHTML.</p>"

        ' Open the destination stream; using ensures the file handle is released after writing
        Using dest As FileStream = File.Create("output.pdf")
            ' pdfHTML maps the HTML tags to iText objects and writes them to the stream (no browser involved)
            HtmlConverter.ConvertToPdf(html, dest)
        End Using
    End Sub
End Class
$vbLabelText   $csharpLabel

Sur un nouveau projet, cela renvoie une erreur jusqu'à ce que vous ajoutiez le package itext7.bouncy-castle-adapter, qu'iText requiert pour son chemin de cryptographie. Cette dépendance supplémentaire est facile à manquer et produit une erreur opaque sans elle.

Avantages :

  • Manipulation profonde des PDF, signature et rédaction dans l'écosystème iText.
  • Produit PDF/A et PDF/UA à partir de HTML sémantique, qui convient au travail de conformité.
  • Temps de démarrage rapide, car il ne lance pas de navigateur.

Inconvénients :

  • Pas d'exécution de script, donc le contenu dynamique ne se rend pas.
  • Les fonctionnalités CSS3 comme Grid ne sont pas prises en charge et échouent silencieusement.
  • La licence AGPLv3 nécessite une licence commerciale pour les applications à source fermée, et les fichiers volumineux sont mis en tampon en entier plutôt que diffusés.

License: AGPLv3 or Commercial. Choisissez-le pour la manipulation intensive de PDF et les flux de travail de conformité avec HTML statique et contrôlé. Pour les détails sur la licence et la manipulation, voir la comparaison iText 7 vs IronPDF.

IronPDF

IronPDF intègre un moteur Chromium dans son package NuGet et l'expose via une API C#, de sorte que rien d'externe n'a besoin d'être lancé ou mis en pool. Il se situe entre les outils de navigateur gratuits et les bibliothèques programmatiques, échangeant un coût de licence pour la fidélité de rendu sans gérer le navigateur.

using IronPdf;
using System.Threading.Tasks;

public class IronPdfExample
{
    public async Task GeneratePdfAsync()
    {
        // Create the in-process Chromium renderer (no external browser to launch)
        var renderer = new ChromePdfRenderer();
        // Turn on the JavaScriptengine so client-side chart scripts execute before capture
        renderer.RenderingOptions.EnableJavaScript = true;
        // Wait 500 ms after load to let JavaScript-built content settle before rendering
        renderer.RenderingOptions.WaitFor.RenderDelay(500);

        // Render the HTML string asynchronously into an in-memory PDF
        var pdf = await renderer.RenderHtmlAsPdfAsync("<h1>Quarterly Report</h1><div class='chart'></div>");
        // Save the finished PDF to disk
        pdf.SaveAs("report.pdf");
    }
}
using IronPdf;
using System.Threading.Tasks;

public class IronPdfExample
{
    public async Task GeneratePdfAsync()
    {
        // Create the in-process Chromium renderer (no external browser to launch)
        var renderer = new ChromePdfRenderer();
        // Turn on the JavaScriptengine so client-side chart scripts execute before capture
        renderer.RenderingOptions.EnableJavaScript = true;
        // Wait 500 ms after load to let JavaScript-built content settle before rendering
        renderer.RenderingOptions.WaitFor.RenderDelay(500);

        // Render the HTML string asynchronously into an in-memory PDF
        var pdf = await renderer.RenderHtmlAsPdfAsync("<h1>Quarterly Report</h1><div class='chart'></div>");
        // Save the finished PDF to disk
        pdf.SaveAs("report.pdf");
    }
}
Imports IronPdf
Imports System.Threading.Tasks

Public Class IronPdfExample
    Public Async Function GeneratePdfAsync() As Task
        ' Create the in-process Chromium renderer (no external browser to launch)
        Dim renderer As New ChromePdfRenderer()
        ' Turn on the JavaScript engine so client-side chart scripts execute before capture
        renderer.RenderingOptions.EnableJavaScript = True
        ' Wait 500 ms after load to let JavaScript-built content settle before rendering
        renderer.RenderingOptions.WaitFor.RenderDelay(500)

        ' Render the HTML string asynchronously into an in-memory PDF
        Dim pdf = Await renderer.RenderHtmlAsPdfAsync("<h1>Quarterly Report</h1><div class='chart'></div>")
        ' Save the finished PDF to disk
        pdf.SaveAs("report.pdf")
    End Function
End Class
$vbLabelText   $csharpLabel

Le même moteur convertit une URL en PDF avec un seul appel :

// RenderUrlAsPdf fetches and renders the live page in one call, no navigation step needed
var fromUrl = new ChromePdfRenderer().RenderUrlAsPdf("https://example.com");
// Write the captured page to disk
fromUrl.SaveAs("from_url.pdf");
// RenderUrlAsPdf fetches and renders the live page in one call, no navigation step needed
var fromUrl = new ChromePdfRenderer().RenderUrlAsPdf("https://example.com");
// Write the captured page to disk
fromUrl.SaveAs("from_url.pdf");
' RenderUrlAsPdf fetches and renders the live page in one call, no navigation step needed
Dim fromUrl = (New ChromePdfRenderer()).RenderUrlAsPdf("https://example.com")
' Write the captured page to disk
fromUrl.SaveAs("from_url.pdf")
$vbLabelText   $csharpLabel

Il rend également les vues Razor et MVC en PDF et convertit directement les fichiers HTML. La présentation complète des fonctionnalités se trouve dans le tutoriel HTML en PDF.

Avantages :

  • Rendu de qualité navigateur qui gère Grid, Flexbox, et les scripts côté client.
  • Déploiement sans exécutables externes ou mise en pool de navigateur.
  • Génère des PDF/A et applique des signatures numériques, ce qui le sépare des frameworks de test.

Inconvénients :

  • Une licence commerciale est requise, sans niveau de production gratuit.
  • Après un déploiement neuf, le premier rendu comporte un coût d'initialisation unique, puis les rendus suivants se stabilisent dans un chemin rapide à chaud.

License: Commercial, perpetual. Utilisez-le là où le CSS actuel en volume importe et où les priorités sont de réduire la charge des opérations tout en maintenant une haute fidélité.

Tableau de comparaison complète

Une ligne par bibliothèque, avec la colonne de licence incluse car elle influence directement la décision entre gratuit et payant.

Bibliothèque Moteur JavaScript CSS moderne Poids du déploiement Licence Idéal pour
IronPDF Chromium intégré Oui Complet Léger (NuGet) Commercial CSS moderne à l'échelle
PuppeteerSharp Chromium externe Oui Complet Lourd (téléchargement binaire) MIT Rendu de navigateur gratuit
Auteur Chromium externe Oui Complet Lourd (téléchargement binaire) MIT Rendu moderne gratuit
wkhtmltopdf Ancien QtWebKit Limité Faible Moyen (libs natifs) LGPLv3 (wrapper MIT) Flux de travail hérités
PdfSharp + HtmlRenderer Dessin personnalisé Non Limité Léger MIT / BSD-3 HTML statique simple
QuestPDF Programmatique N/A N/A Léger Communauté / Payant Mises en page définies par le code
iText pdfHTML Analyseur personnalisé Non Limité Moyen AGPLv3 / Commercial Manipulation PDF

Vérifiez chaque cellule par rapport à la version actuelle de chaque bibliothèque avant l'intégration, car les licences et le support des moteurs changent.

Gratuit vs Payant : quand chacun est le bon choix

Les outils " gratuits " peuvent cacher des coûts opérationnels et juridiques dans le domaine PDF .NET, donc nommer les cas où un outil gratuit est le bon choix est le point de départ honnête.

Une bibliothèque open-source gratuite est vraiment suffisante pour des documents simples et statiques, un faible volume ou une équipe avec la capacité opérationnelle de gérer les processus externes. Un reçu riche en texte sans style complexe se rend bien avec PdfSharp sous licence MIT. Lorsqu'une équipe utilise déjà Auteurpour les tests et qu'elle a résolu la containerisation, le réutiliser pour des tâches ponctuelles de PDF est efficace.

Logiciel gratuit ne signifie pas implantation gratuite. Le coût caché des navigateurs sans tête open-source apparaît en heures de maintenance : gérer le cycle de vie du navigateur pour que le serveur ne tombe pas en panne sous la charge, configurer les dépendances des bibliothèques partagées Linux sur les images de conteneur, et absorber le coût infrastructurel des processus de navigateur lourds. Pour des documents statiques triviaux, un moteur de navigateur payant est exagéré, et une bibliothèque légère et gratuite est le meilleur choix.

Une bibliothèque Chromium commerciale devient justifiée lorsque le travail exige un CSS3 précis à grande échelle, une sortie PDF/UA accessible, et une simplicité de déploiement par rapport au coût d'approvisionnement. La licence commerciale élimine également l'exposition copyleft. Ajouter une bibliothèque AGPLv3 comme iText à une plateforme SaaS peut obliger l'entreprise à publier son code source à moins qu'une licence commerciale ne soit achetée. La vraie comparaison est le coût total de possession : temps des opérations et risque juridique d'un côté, frais de licence de l'autre.

Benchmarks

Chaque chiffre ci-dessous provient d'une exécution pratique sur une seule machine, donc traitez-les comme directionnels. Le document de test est une facture de 30 lignes utilisant CSS Grid dans l'en-tête et un graphique en bâtons JavaScripten ligne. Les tests ont été effectués sur un poste de travail Windows standard sous .NET 10. Chaque chiffre à chaud est la moyenne de huit rendus après le premier, et la mémoire de pointe est le pic de l'ensemble de travail du processus .NET plus tous les processus enfants du navigateur qu'il a générés.

Bibliothèque Démarrage à froid (par processus) Rendu à chaud (moyenne de 8) Mémoire de pointe
IronPDF 345 ms 202 ms 406 Mo
PuppeteerSharp 746 ms 204 ms 611 Mo
Auteur 588 ms 132 ms 515 Mo
wkhtmltopdf, iText, PdfSharp sub-second not comparable 50 à 120 Mo

Une fois à chaud, les trois moteurs de navigateur rendent le même document en environ 130 à 200 ms, avec Auteurle plus rapide dans cette exécution et IronPDFetPuppeteerSharpjuste derrière. Au démarrage à froid, le moteur intégré a démarré le plus rapidement ici car il fonctionne in-process sans navigateur séparé à lancer, bien que le tout premier rendu après un déploiement tout neuf absorbe un coût d'initialisation unique que les démarrages de processus ultérieurs sautent. Les outils hérités et parseurs personnalisés (wkhtmltopdf, iText, PdfSharp) démarrent en moins d'une seconde et utilisent le moins de mémoire, mais cet avantage est inutile pour le document de test, car ils ne peuvent pas rendre correctement sa mise en page Grid ou son graphique JavaScript. wkhtmltopdf n'a pas pu fonctionner du tout sans ses binaires natifs fournis au préalable.

L'écart de fidélité se voit dans la sortie. Le moteur de navigateur rend l'en-tête CSS Grid, la table stylée et le graphique en bâtons JavaScript:

La facture de test rendue par un moteur Chromium, avec l'en-tête CSS Grid, la table stylée et le graphique en bâtons JavaScripttous présents

Le même document via PdfSharp avec HtmlRenderer omet l'en-tête de grille, le style d'en-tête de table et le graphique JavaScript:

La même facture rendue par PdfSharp avec HtmlRenderer, manquant l'en-tête CSS Grid et le graphique JavaScript

Lequel devriez-vous utiliser ?

Un verdict court pour chaque scénario commun :

  • Frameworks CSS et sortie en page unique : seul un moteur de rendu de niveau navigateur peut suivre.
  • HTML statique simple ou reçus textes : PdfSharp et une petite pile gratuite le couvrent.
  • Mises en page programmatiques basées sur des données, sans balisage : QuestPDF y arrive le plus rapidement.
  • Rendu de navigateur gratuit avec capacité opérationnelle :PuppeteerSharpou Playwright.
  • Zéro infrastructure : une API de conversion HTML en PDF hébergée.
  • Migration wkhtmltopdf héritée : déplacer vers un moteur intégré pour la sécurité et le support CSS.

Lorsque la sortie d'un framework CSS lourd répond à un besoin de faibles opérations,IronPDF est l'option intégrée à choisir en premier, tandis que les outils de navigateur gratuits restent le bon choix pour les équipes pouvant posséder les opérations autour d'un navigateur sans tête.

Considérations de déploiement

La plus grande friction dans la génération de documents .NET est l'écart entre une bibliothèque qui fonctionne sur un ordinateur portable Windows et une qui échoue sur un conteneur Linux. Sélectionner une bibliothèque signifie anticiper où elle sera expédiée.

Dans Docker, les navigateurs orchestrés tels quePuppeteerSharpet Auteurnécessitent une image de base contenant les dépendances Linux de Chromium, y compris libnss3, libatk-bridge2.0-0, et libgbm1. Microsoft publie des images Auteur.NET at mcr.microsoft.com/playwright/dotnet (par exemple, un tag v1.NN.0-noble) pour couvrir ces besoins, et ces images tournent autour d'un gigaoctet. Les moteurs intégrés contournent le gonflement en expédiant des packages NuGet par architecture, tels que IronPdf.Linux, qui comprennent les binaires natifs et maintiennent une image de base standard aspnet fonctionnant sans étapes apt-get manuelles.

AWS Lambda soulève un autre obstacle. Il impose une limite dure de 250 Mo sur le package de déploiement décompressé, mais une version Chromium sans tête seule représente de 150 Mo à 300 Mo. Cela rend impossible un déploiement standard en zip dePuppeteerSharpou Auteuret pousse les équipes vers Lambda basé sur conteneur, qui permet jusqu'à 10 Go au prix d'un démarrage à froid plus lent.

Azure App Service ajoute ses propres contraintes sur les deux systèmes d'exploitation. Le sandbox Windows App Service bloque la plupart des appels User32 et GDI32 et brise ainsi les chemins de rendu dépendants de GDI. Déployer DinkToPdf sur Linux App Service signifie copier les fichiers .so non gérés dans la sortie et installer des dépendances telles que libfontconfig1 et libxrender1 ; une dépendance manquante apparaît comme une erreur opaque System.DllNotFoundException. Ce sont les mêmes problèmes de dépendance native et de sandbox que l'exécution de vérification a reproduits.

Conclusion and recommendation

Le domaine HTML en PDF C# sur .NET 10 récompense le bon appareillage de l'outil au document. Un moteur de navigateur complet est la base pour les frameworks CSS et les mises en page réactives et les pages pilotées par JavaScript, et la division entre gratuit et commercial est en réalité une division entre effort opérationnel et coût de licence. Les bibliothèques programmatiques restent efficaces pour des mises en page fixes, statiques, et QuestPDF est le chemin le plus rapide lorsque l'entrée est constituée de données structurées plutôt que de balisage. wkhtmltopdf appartient uniquement aux plans de migration, étant donné son moteur archivé et son défaut SSRF non corrigé. Pour les équipes souhaitant un rendu précis sans beaucoup de charge opérationnelle,IronPDF est l'option intégrée par défaut, avec URL vers PDF, rendu de vue Razor, sortie PDF/A, et signatures numériques disponibles depuis la même API, tandis quePuppeteerSharpet Auteurrestent de solides choix gratuits là où le cycle de vie du navigateur est quelque chose que l'équipe peut maîtriser.

Essayez-le sur votre propre HTML

Si un rendu précis avec un coût d'expédition léger convient à votre projet, vous pouvez commencer un essai gratuit de IronPDF et exécuter cette même facture test sur vos propres modèles avant de vous engager.IronPDFest développé par Iron Software, dont les bibliothèques .NET couvrent également OCR, barcodes, Word et Excel.

Merci de votre lecture. Quelle que soit la bibliothèque que vous choisissez, adaptez-la au document devant vous.

Veuillez noterIronPDF is a product of Iron Software. PuppeteerSharp, Playwright, wkhtmltopdf, DinkToPdf, PdfSharp, HtmlRenderer, QuestPDF, et iText sont des projets ou marques déposées de leurs propriétaires respectifs. Cet article n'est pas affilié, approuvé ou sponsorisé par ces projets. Les comparaisons reflètent les informations disponibles publiquement et les tests pratiques au moment de l'écriture ; vérifiez les détails actuels de la licence et de la publication avant de vous y fier.

Questions Fréquemment Posées

What are the main types of C# HTML to PDF libraries available for .NET 10 in 2026?

The main types of C# HTML to PDF libraries for .NET 10 in 2026 include browser-based engines like Chromium using PuppeteerSharp or Playwright, programmatic libraries such as iText and PdfSharp, and code-first layout tools like QuestPDF.

How do browser-based engines compare to programmatic libraries for HTML to PDF conversion?

Browser-based engines render modern CSS and JavaScript accurately, providing high fidelity to web standards, whereas programmatic libraries like iText and PdfSharp trade some web fidelity for a smaller footprint by drawing PDFs from custom parsers.

What advantages do code-first layout tools offer over traditional HTML to PDF methods?

Code-first layout tools like QuestPDF allow developers to skip HTML entirely, often resulting in more efficient and customizable PDF generation tailored to specific application needs.

Why is choosing the right rendering engine important for HTML to PDF conversion?

Choosing the right rendering engine is crucial because it determines how accurately your documents are rendered, especially in terms of modern CSS and JavaScript fidelity, which is important for maintaining the visual integrity of your PDFs.

What role do licensing terms play in selecting a C# HTML to PDF library?

Licensing terms are important as they dictate what you can legally do with the library, such as distributing the software commercially, and can affect the overall cost and feasibility of using the library in your projects.

Are there free options available for C# HTML to PDF conversion?

Yes, there are free options available, though they may come with limitations in terms of features and support compared to paid alternatives. It's important to weigh these against your project needs.

How do benchmarks help in evaluating C# HTML to PDF libraries?

Benchmarks provide a quantitative measure of performance, allowing developers to compare libraries based on speed, resource usage, and output quality, helping in making an informed decision.

What is the significance of runnable code examples in library comparisons?

Runnable code examples are significant as they allow developers to test libraries in real-world scenarios, providing insights into ease of use, integration complexity, and how well a library fits specific project requirements.

Can IronPDF be a suitable option for HTML to PDF conversion in .NET 10?

Yes, IronPDF is a suitable option, known for its ease of use, comprehensive features, and support for modern web standards, making it a strong contender for HTML to PDF conversion in .NET 10.

Curtis Chau
Rédacteur technique

Curtis Chau détient un baccalauréat en informatique (Université de Carleton) et se spécialise dans le développement front-end avec expertise en Node.js, TypeScript, JavaScript et React. Passionné par la création d'interfaces utilisateur intuitives et esthétiquement plaisantes, Curtis aime travailler avec des frameworks modernes ...

Lire la suite

Équipe de soutien Iron

Nous sommes en ligne 24 heures sur 24, 5 jours sur 7.
Chat
Email
Appelez-moi