Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige
Lesedauer 5 Min.

Aus HTML mach PDF

So setzen Sie das NuGet-Package DinkToPdf ein.
© dotnetpro
Es existieren zahlreiche kommerzielle Bibliotheken für das Erstellen von PDF-Dateien in C#, wie zum Beispiel IronPDF [1] und Aspose.PDF [2]. Wer eine kostenfreie Bibliothek für die Erstellung von PDF-Dateien sucht, kann beispielsweise zwischen PDFsharp [3] und DinkToPdf [4] wählen.Mit PDFsharp werden die PDF-Dateien mit Zeichenroutinen, die aus GDI+ bekannt sind, erstellt. Fast alle Funktionen von GDI+ sind auch in PDFsharp verfügbar [5].Im Gegensatz dazu wandelt DinkToPdf HTML-Code in PDF-Dateien um, wobei auch CSS-Formatierungen möglich sind. Aufgrund der Vertrautheit vieler Webentwickler mit HTML wird die Entscheidung vermutlich zugunsten von DinkToPdf fallen.

Installation und Konfiguration von DinkToPdf

DinkToPdf, eine plattformübergreifende Bibliothek, fungiert als Wrapper für die wkhtmltopdf-Bibliothek. wkhtmltopdf ist ein Open-Source-Befehlszeilentool (LGPLv3), das HTML-Code unter Verwendung einer WebKit-Rendering-Engine in PDF umwandelt [6].DinkToPdf ist als NuGet-Package in der Version 1.08 verfügbar und kann über den NuGet-Paket-Manager oder mit dem Befehl Install-Package DinkToPdf über die Paket-Manager-Konsole installiert werden. Dabei werden die DLL-Dateien aus der wkhtmltopdf-Bibliothek nicht automatisch installiert; diese müssen manuell zum Projekt hinzugefügt werden.Wir installieren jedoch die benötigte DLL-Datei aus der wkhtmltopdf-Bibliothek zunächst nicht, damit wir die entsprechende Fehlermeldung generieren können, die auftritt, wenn die DLL-Datei fehlt.In unserem Beispiel verwenden wir eine MVC-Webseite, .NET 8 und C#. Zunächst installieren wir das NuGet-Pa­ckage DinkToPdf. Anschließend wird der Service in der Datei Program.cs wie folgt registriert:

var converter = new SynchronizedConverter(
  new PdfTools());
builder.Services.AddSingleton(converter); 
Hiermit haben wir den HTML-zu-PDF-Converter aus dem NuGet-Package DinkToPdf als Service registriert und können diesen mittels Dependency Injection überall in unserem Projekt verwenden.

Konfiguration der PDF-Seite

DinkToPdf bietet drei Hauptklassen für die Konfiguration:
  • Die Klasse GlobalSettings besteht aus den allgemeinen Konfigurationseigenschaften für das PDF-Dokument. Wir verwenden nur einige dieser Eigenschaften, um den Farbmodus, die Ausrichtung, das Papierformat, den Dokumententitel der Seite einzurichten.
  • Die Klasse ObjectSettings besteht aus den Eigenschaften, die mit dem Inhalt des PDF-Dokuments zusammenhängen. Hier können wir zum einen die Paginierung und den Inhalt der Kopf- und Fußzeilen festlegen. Zum anderen gibt es noch die Web-Einstellungen und die HtmlContent-Eigenschaft. In den Web-Einstellungen der ObjectSettings lässt sich auch festlegen, ob JavaScript aktiviert sein soll oder nicht und ob eine – und welche – Style-Sheet-Datei für das Rendern des HTML-Codes verwendet werden soll. In unserem Beispiel ist das die Datei PDFstyles.css im Ordner wwwroot/css; diese formatiert die Tabelle mit einem blauen Header und einem blauen Rahmen (Listing 1). Die Html­Content-­Eigenschaft ist eine sehr wichtige Eigenschaft dieser Klasse; ihr wird später die von uns generierte HTML-Vorlage übergeben.
Listing 1: Inhalt der Datei PDFstyles.css
h1 {
  color: blue;
  text-align: center;
}
table {
  width: 100%;
  border-collapse: collapse;
}
table, th, td {
  border: 1px solid blue;
  font-size: 22px;
}
td, th {
  padding: 10px;
}
th {
  background-color: blue;
  color: white;
  text-align: left;
}  
  • Zuletzt gibt es noch die Klasse HtmlToPdfDocument, welche die GlobalSettings und ObjectSettings als Eigenschaften beinhaltet.
GlobalSettingsObjectSettingsUm sich die Arbeit zu vereinfachen und die Konfiguration der PDF-Datei immer wieder verwenden zu können, wird diese in eine separate Klasse ausgelagert, die uns das fertig konfigurierte Objekt HtmlToPdfDocument zurückgibt (siehe Listing 2). Später wird dann noch der HTML-Code an das Objekt HtmlToPdfDocument übergeben.
Listing 2: Die Eigenschaften unserer PDF-Datei werden in einer separaten Klasse gesetzt
public class PdfConfigSettings
{
  public static HtmlToPdfDocument 
      GetHtmlToPdfDocument()
  {
    var globalSettings = new GlobalSettings
    {
      ColorMode = ColorMode.Color,
      Orientation = Orientation.Portrait,
      PaperSize = PaperKind.A4,
      Margins = new MarginSettings {Top = 10},
      DocumentTitle = "",
    };
    var objectSettings = new ObjectSettings
    {
      PagesCount = true,
      HtmlContent = "",  // hier wird später der 
                            HTML-Code eingefügt
      WebSettings = { 
        DefaultEncoding = "utf-8", 
        EnableJavascript = false, 
        UserStyleSheet = Path.Combine(
          Directory.GetCurrentDirectory(),
          "wwwroot/css", "PDFstyles.css") 
      },
      FooterSettings = { 
        FontName = "Calibri, Arial", 
        FontSize = 8, 
        Right = "Seite [page] von [toPage]", 
        Line = false }
    };
    var htmlToPdfDocument = new HtmlToPdfDocument()
    {
      GlobalSettings = globalSettings,
      Objects = { objectSettings }
    };
    return htmlToPdfDocument;
  }
} 

Erstellung von Beispieldaten für das PDF-Dokument

In unserem Beispiel möchten wir Informationen über die Mitglieder eines fiktiven Vereins als PDF-Datei ausgeben und auf der Webseite anzeigen und dort auch zum Download anbieten. Dazu wurde zunächst eine Klasse Members und danach ­eine Klasse ­Data mit einer Methode Get­AllMembers() erstellt. Die Methode ­GetAllMembers() gibt eine Liste von 20 Mitgliedern zurück; diese Mitgliederdaten wurden mittels ChatGPT ­erstellt.

Generierung des HTML-Codes

Jetzt brauchen wir noch eine Methode, die uns eine Tabelle mit den Mitgliederdaten in HTML zurückgibt. Mittels einer Klasse PdfReportGenerator sowie der Methode GetHTML­String() lassen wir uns den HTML-Code für unsere Mitgliederliste erstellen (Listing 3).
Listing 3: Die Klasse PdfReportGenerator zum Erstellen des HTML-Codes
public static class PdfReportGenerator
{
  public static string GetHTMLString()
  {
    var members = Data.GetAllMembers();
    var sb = new StringBuilder();
    sb.Append(@"
                <html>
                  <head>
                  </head>
                  <body>
                    <div class='header'>
                      <h1>Mitglieder-Liste</h1></div>
                    <table align='center'>
                      <tr>
                        <th>Name</th>
                        <th>Vorname</th>
                        <th>Strasse</th>
                        <th>PLZ</th>
                        <th>Ort</th>
                      </tr>");
    foreach (var member in members)
    {
      sb.AppendFormat(@"<tr>
                          <td>{0}</td>
                          <td>{1}</td>
                          <td>{2}</td>
                          <td>{3}</td>
                          <td>{4}</td>
                        </tr>", 
                        member.Firstname, member.
                          LastName, member.Street, 
                        member.PLZ, member.City);
    }
    sb.Append(@"
                    </table>
              </body>
       </html>");
    return sb.ToString();
  }
} 
In unserem Controller können wir in der Methode Show­PDF() nun mit vier Codezeilen die PDF-Datei ausgeben, siehe Listing 4. Zunächst lassen wir uns mit der Methode Get­HtmlTo­PdfDocument() aus der Klasse PdfConfigSettings ein bereits konfiguriertes Objekt der Klasse HtmlToPdfDocument zurückgeben. Anschließend übergeben wir an die Eigenschaft ­HtmlContent den HTML-Code, den wir uns mit Get­HTMLString() aus der Klasse PdfReportGenerator zurück­geben lassen.
Listing 4: Die PDF-Datei im Controller ausgeben
using CreatePDFOnWeb.PDFHelper;
using DinkToPdf;
using DinkToPdf.Contracts;
using Microsoft.AspNetCore.Mvc;
namespace CreatePDFOnWeb.Controllers
{
  public class PdfController : Controller
  {
    private readonly IConverter _converter; 
    public PdfController(IConverter converter)
    {
      _converter = converter;
    }
    public IActionResult ShowPDF()
    {
      HtmlToPdfDocument htmlToPdfDocument = 
        PdfConfigSettings.GetHtmlToPdfDocument();
      htmlToPdfDocument.Objects[0].HtmlContent = 
        PdfReportGenerator.GetHTMLString();
      byte[] file = _converter.Convert(
        htmlToPdfDocument);
      return File(file, "application/pdf");
    }
  }
} 

Ausgabe der PDF-Datei – schlägt fehl

Nun übergeben wir das HtmlToPdfDocument-Objekt an den Converter-Service, den wir per Dependency Injection in den Kontroller eingebunden haben. Als Ergebnis erhalten wir ein Byte-Array. Jetzt müssen wir nur noch das Byte-Array als File mit dem ContentTypeapplication/pdf zurückgeben, und die PDF-Datei sollte im Browser angezeigt werden.

Externe DLL-Datei hinzufügen und registrieren

Mit dem bisherigen Code funktioniert das jedoch noch nicht. Die Anwendung lässt sich kompilieren und starten, doch erhalten wir beim Versuch, die PDF-Seite auszugeben, einen Laufzeitfehler (siehe Bild 1). Die Fehlermeldung „Unable to load DLL 'libwkhtmltox' or one of its dependencies:“ weist auf eine fehlende DLL-Datei namens libwkhtmltox hin.
Fehlermeldung wegen fehlender DLL-Datei (Bild 1) © Autor
Die benötigte DLL-Datei lässt sich aus dem DinkToPdf-­Repository bei GitHub [4] herunterladen und im Projekt platzieren; libwkhtmltox.dll findet sich im Ordner \v0.12.4\64 bit. Wir kopieren sie in unserem Beispiel in den Ordner wwwroot\pdfCreatorDll. Damit unsere Anwendung diese DLL-Datei finden und verwenden kann, müssen wir sie zunächst registrieren.Dazu haben wir eine Klasse CustomAssemblyLoadContext
.cs
angelegt (Listing 5). Diese erbt von der Klasse AssemblyLoadContext und überschreibt die Methoden LoadUnma­nagedLibrary und LoadUnmanagedDll.
Listing 5: Inhalt der Klasse CustomAssemblyLoadContext
public class CustomAssemblyLoadContext : 
    AssemblyLoadContext
{
  public nint LoadUnmanagedLibrary(
    string absolutePath)
  {
    return LoadUnmanagedDll(absolutePath);
  }
  protected override nint LoadUnmanagedDll(
    string unmanagedDllName)
  {
    return LoadUnmanagedDllFromPath(unmanagedDllName);
  }
} 
Zuletzt müssen wir noch das Laden der DLL-Datei in der Datei Program.cs initiieren (Listing 6).
Listing 6: Die benötigten Einträge in der Datei Program.cs
// register libwkhtmltox.dll 
var contentRootPath = 
  builder.Environment.ContentRootPath;
var libwkhtmltoxPath = Path.Combine(contentRootPath, 
  $"wwwroot\\pdfCreatorDll\\libwkhtmltox.dll");
var assemblyLoadContext = 
  new CustomAssemblyLoadContext();
assemblyLoadContext.LoadUnmanagedLibrary(
  libwkhtmltoxPath);
// register service DinkToPdf
var converter = new SynchronizedConverter(
  new PdfTools());
builder.Services.AddSingleton<IConverter>(converter); 

PDF-Datei im Webbrowser erstellen

Nach Abschluss dieser Schritte ist die PDF-Erstellung in der Webanwendung realisierbar (siehe Bild 2).
Ansicht der PDF-Datei im Browser (Bild 2) © Autor
Das Codebeispiel dieses Artikels kann unter [7] he­runtergeladen werden.

Fussnoten

  1. IronPDF, The C# PDF Library,
  2. Aspose.PDF for .NET Documentation,
  3. PDFsharp,
  4. DinkToPdf auf GitHub,
  5. PDFsharp & MigraDoc, Overview,
  6. wkhtmltopdf,
  7. ChristianKiefer / CreatePDFOnWebsites auf GitHub,

Neueste Beiträge

Müssen Ziele SMART sein?
Wenn es um Ziele im Projektmanagement oder in der Führung einer Organisation geht, stoßen wir schnell und fast ausnahmslos auf das Akronym SMART. Was steckt dahinter, und kann es nicht auch sinnvolle Ziele geben, die nicht SMART sind?
8 Minuten
Managed DevOps Pools - Azure DevOps Pipelines Security
Agent Pools als Managed Service mit einfacher Integration in private Netzwerke und Authentisierung mittels Managed Identity tragen deutlich zur Sicherheit der Agent-Infrastruktur bei.
7 Minuten
7. Aug 2025
Arbeiten mit Tabellen und KI in Dataverse
Microsoft unterstützt die zentrale Datenmanagement-Lösung Dataverse in Power Apps mit KI-Features.
7 Minuten
6. Aug 2025
Miscellaneous

Das könnte Dich auch interessieren

Sicher ist sicher - Azure DevOps Pipelines Security
Als integraler Bestandteil der Entwicklungsumgebung ist Azure DevOps Pipelines oft Ziel von Angriffen. Da ist es gut zu wissen, wo die Schwachstellen des Systems liegen.
14 Minuten
16. Jun 2025
CodeProject.AI Server in neuer Version - Lokaler AI-Server
CodeProject.AI Server (jetzt in Version 2.1.10) ist ein lokal installierter, selbstgehosteter, schneller, kostenloser und Open Source Artificial Intelligence Server für jede Plattform und jede Sprache.
2 Minuten
Für Einsteiger: Backend-Webentwicklung mit .NET - Microsoft
Auf YouTube bietet Microsoft eine Videoserie für Einsteiger in die Backend-Webentwicklung mit .NET.
2 Minuten
13. Feb 2024
Anzeige
Anzeige
Anzeige
Anzeige
Anzeige