Przejdź do treści stopki
PRZEWODNIKI MIGRACJI

Jak przejść z wkhtmltopdf na IronPDF w języku C#

wkhtmltopdf był szeroko używanym narzędziem do konwersji dokumentów HTML do PDF przy użyciu Qt 4.8 + QtWebKit. Pomimo popularności wśród programistów ze względu na możliwości wiersza poleceń i bezpłatną licencję, projekt stwarza obecnie poważne zagrożenia dla bezpieczeństwa, których nie można już dłużej ignorować. Repozytorium GitHub zostało zarchiwizowane 2 stycznia 2023 roku; ostatnie wydanie upstream to 0.12.6 z 11 czerwca 2020 roku; i CVE-2022-35583 (CVSS 9.8, SSRF) pozostaje niezałatane.

Niniejszy przewodnik zawiera kompletną ścieżkę migracji z wkhtmltopdf do IronPDF, wraz z instrukcjami krok po kroku, porównaniami kodu i praktycznymi przykładami dla profesjonalnych programistów .NET, którzy muszą wyeliminować to zagrożenie bezpieczeństwa ze swoich aplikacji.

Krytyczne ostrzeżenie dotyczące bezpieczeństwa: CVE-2022-35583

wkhtmltopdf zawiera krytyczną lukę w zabezpieczeniach, która nigdy nie zostanie naprawiona:

Problem Szczegóły Status
CVE-2022-35583 (SSRF, CWE-918) KRYTYCZNY (CVSS 9.8) NIEZAŁATANY — sporny przez utrzymujących
Repozytorium GitHub zarchiwizowane Tylko do odczytu 2 stycznia 2023
Ostatnie wydanie upstream 0.12.6 11 czerwca 2020
Podstawowy silnik Qt 4.8 + QtWebKit (Qt 4.8 EOL 2015) NIEAKTUALNE
Obsługa CSS Grid None Uszkodzone
Obsługa Flexbox Częściowe Uszkodzone
JavaScript ES6+ Ograniczone Uszkodzone

Jak działa atak SSRF

Luka typu Server-Side Request Forgery pozwala atakującym uzyskać dostęp do usług wewnętrznych, wykraść dane uwierzytelniające, skanować sieć wewnętrzną i wykradać poufne dane za pomocą spreparowanego kodu HTML:


<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin"/>

<iframe src="http://169.254.169.254/latest/meta-data/iam/security-credentials/"></iframe>
<img src="http://internal-database:5432/admin"/>
HTML

Kiedy wkhtmltopdf renderuje ten kod HTML, pobiera te adresy URL z kontekstu sieciowego serwera, omijając zapory sieciowe i zabezpieczenia.

Biblioteki opakowujące, których to dotyczy

Każdy wrapper .NET pakietuje lub korzysta z tej samej natywnej wersji binarnej wkhtmltopdf, dlatego wszystkie dziedziczą jego narażenie na CVE, bez względu na aktywność samego wrappera:

Biblioteka opakowująca Najnowsze NuGet Zagrożenie bezpieczeństwa
DinkToPdf 1.0.8 (kwiecień 2017) — porzucony Dziedziczy CVE-2022-35583
Rotativa.AspNetCore (webgio fork) 1.4.0 (listopad 2023) — wrapper zaktualizowany, binarny zamrożony Dziedziczy CVE-2022-35583
TuesPechkin 2.1.1 (styczeń 2015) — porzucony Dziedziczy CVE-2022-35583
Haukcode.WkHtmlToPdfDotNet (formerly WkHtmlToPdf-DotNet) 1.5.95 (październik 2024) — wrapper zaktualizowany, binarny zamrożony Dziedziczy CVE-2022-35583
NReco.PdfGenerator wrapper zaktualizowany, pakietuje wkhtmltopdf Dziedziczy CVE-2022-35583

Jeśli używasz którejkolwiek z tych bibliotek, twoja aplikacja jest narażona na CVE-2022-35583, chyba że oczyścisz cały wejściowy HTML.

IronPDF a wkhtmltopdf: porównanie funkcji

Zrozumienie różnic architektonicznych pomaga decydentom technicznym w ocenie inwestycji w migrację:

Funkcja wkhtmltopdf IronPDF
Licencjonowanie LGPLv3 (bezpłatna) Komercjalne
Silnik renderujący Qt 4.8 + QtWebKit (Qt 4.8 EOL 2015) Obecny silnik Chromium
Luki w zabezpieczeniach CVE-2022-35583 (CVSS 9.8) niezałatany, sporny Brak zgłoszonych krytycznych CVE
Aktywna konserwacja Repozytorium GitHub zarchiwizowane 2 stycznia 2023; ostatnie wydanie czerwiec 2020 Aktywnie utrzymywany z regularnymi wydaniami
Obsługa nowoczesnych standardów internetowych Ograniczone (uszkodzony flexbox, brak CSS Grid) Obsługiwane
Integracja i wsparcie Ograniczone do forów społecznościowych Obszerna dokumentacja i dedykowane wsparcie
CSS Grid ❌ Nieobsługiwane ✅ Obsługiwane
Flexbox ⚠ Uszkodzony ✅ Obsługiwane
JavaScript ES6+ ❌ Nieobsługiwane ✅ Obsługiwane
Async/Await ❌ Nieobsługiwane ✅ Obsługiwane
Manipulacja plikami PDF ❌ Nieobsługiwane ✅ Obsługiwane
Podpisy cyfrowe ❌ Nieobsługiwane ✅ Obsługiwane
Zgodność z PDF/A ❌ Nieobsługiwane ✅ Obsługiwane

Szybki start: Migracja z wkhtmltopdf do IronPDF

Migrację można rozpocząć natychmiast, wykonując te podstawowe kroki.

Krok 1: Usuń pakiety i pliki binarne wkhtmltopdf

Usuń wszystkie pakiety opakowujące wkhtmltopdf:

# Remove wkhtmltopdf wrapper (whichever you're using)
dotnet remove package Haukcode.WkHtmlToPdfDotNet
dotnet remove package DinkToPdf
dotnet remove package TuesPechkin
dotnet remove package Rotativa
dotnet remove package Rotativa.AspNetCore
dotnet remove package NReco.PdfGenerator

# Remove wkhtmltopdf binary from your deployment
# Delete wkhtmltopdf.exe, wkhtmltox.dll, etc.
# Remove wkhtmltopdf wrapper (whichever you're using)
dotnet remove package Haukcode.WkHtmlToPdfDotNet
dotnet remove package DinkToPdf
dotnet remove package TuesPechkin
dotnet remove package Rotativa
dotnet remove package Rotativa.AspNetCore
dotnet remove package NReco.PdfGenerator

# Remove wkhtmltopdf binary from your deployment
# Delete wkhtmltopdf.exe, wkhtmltox.dll, etc.
SHELL

Krok 2: Zainstaluj IronPDF

# Add IronPDF(secure, modern alternative)
dotnet add package IronPdf
# Add IronPDF(secure, modern alternative)
dotnet add package IronPdf
SHELL

Krok 3: Aktualizacja przestrzeni nazw

Zastąp przestrzenie nazw wkhtmltopdf przestrzenią nazw IronPDF:

// Before (wkhtmltopdf)
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;

// After (IronPDF)
using IronPdf;
// Before (wkhtmltopdf)
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;

// After (IronPDF)
using IronPdf;
Imports IronPdf
$vbLabelText   $csharpLabel

Krok 4: Inicjalizacja licencji

Dodaj inicjalizację licencji podczas uruchamiania aplikacji:

IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY";
IronPdf.License.LicenseKey = "YOUR-LICENSE-KEY"
$vbLabelText   $csharpLabel

Przykłady migracji kodu

Konwersja HTML do PDF

Najbardziej podstawowa operacja ujawnia różnicę w złożoności między tymi podejściami do obsługi plików PDF w środowisku .NET.

Podejście wkhtmltopdf:

// NuGet: Install-Package Haukcode.WkHtmlToPdfDotNet
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;
using System.IO;

class Program
{
    static void Main()
    {
        var converter = new SynchronizedConverter(new PdfTools());
        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Portrait,
                PaperSize = PaperKind.A4
            },
            Objects = {
                new ObjectSettings()
                {
                    HtmlContent = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>"
                }
            }
        };
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("output.pdf", pdf);
    }
}
// NuGet: Install-Package Haukcode.WkHtmlToPdfDotNet
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;
using System.IO;

class Program
{
    static void Main()
    {
        var converter = new SynchronizedConverter(new PdfTools());
        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Portrait,
                PaperSize = PaperKind.A4
            },
            Objects = {
                new ObjectSettings()
                {
                    HtmlContent = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>"
                }
            }
        };
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("output.pdf", pdf);
    }
}
Imports Haukcode.WkHtmlToPdfDotNet
Imports Haukcode.WkHtmlToPdfDotNet.Contracts
Imports System.IO

Module Program
    Sub Main()
        Dim converter As New SynchronizedConverter(New PdfTools())
        Dim doc As New HtmlToPdfDocument() With {
            .GlobalSettings = New GlobalSettings() With {
                .ColorMode = ColorMode.Color,
                .Orientation = Orientation.Portrait,
                .PaperSize = PaperKind.A4
            },
            .Objects = New List(Of ObjectSettings) From {
                New ObjectSettings() With {
                    .HtmlContent = "<h1>Hello World</h1><p>This is a PDF from HTML.</p>"
                }
            }
        }
        Dim pdf As Byte() = converter.Convert(doc)
        File.WriteAllBytes("output.pdf", pdf)
    End Sub
End Module
$vbLabelText   $csharpLabel

Podejście IronPDF:

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML.</p>");
        pdf.SaveAs("output.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML.</p>");
        pdf.SaveAs("output.pdf");
    }
}
Imports IronPdf
Imports System

Class Program
    Shared Sub Main()
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderHtmlAsPdf("<h1>Hello World</h1><p>This is a PDF from HTML.</p>")
        pdf.SaveAs("output.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

wkhtmltopdf wymaga utworzenia SynchronizedConverter z PdfTools, skonstruowania HtmlToPdfDocument z GlobalSettings i Objects, ustawienia właściwości takich jak ColorMode, Orientation i PaperSize, wywołania converter.Convert() w celu uzyskania surowych bajtów i ręcznego zapisania do pliku przy użyciu File.WriteAllBytes().

IronPDF całkowicie eliminuje tę ceremonię — utwórz ChromePdfRenderer, wywołaj RenderHtmlAsPdf() i użyj wbudowanej metody SaveAs().

W przypadku zaawansowanych scenariuszy konwersji HTML do PDF zapoznaj się z przewodnikiem po konwersji HTML do PDF.

Konwersja adresów URL do formatu PDF

Konwersja adresów URL do formatu PDF wykazuje podobne wzorce złożoności.

Podejście wkhtmltopdf:

// NuGet: Install-Package Haukcode.WkHtmlToPdfDotNet
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;
using System.IO;

class Program
{
    static void Main()
    {
        var converter = new SynchronizedConverter(new PdfTools());
        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Portrait,
                PaperSize = PaperKind.A4
            },
            Objects = {
                new ObjectSettings()
                {
                    Page = "https://www.example.com"
                }
            }
        };
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("webpage.pdf", pdf);
    }
}
// NuGet: Install-Package Haukcode.WkHtmlToPdfDotNet
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;
using System.IO;

class Program
{
    static void Main()
    {
        var converter = new SynchronizedConverter(new PdfTools());
        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Portrait,
                PaperSize = PaperKind.A4
            },
            Objects = {
                new ObjectSettings()
                {
                    Page = "https://www.example.com"
                }
            }
        };
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("webpage.pdf", pdf);
    }
}
Imports Haukcode.WkHtmlToPdfDotNet
Imports Haukcode.WkHtmlToPdfDotNet.Contracts
Imports System.IO

Module Program
    Sub Main()
        Dim converter As New SynchronizedConverter(New PdfTools())
        Dim doc As New HtmlToPdfDocument() With {
            .GlobalSettings = New GlobalSettings() With {
                .ColorMode = ColorMode.Color,
                .Orientation = Orientation.Portrait,
                .PaperSize = PaperKind.A4
            },
            .Objects = New List(Of ObjectSettings) From {
                New ObjectSettings() With {
                    .Page = "https://www.example.com"
                }
            }
        }
        Dim pdf As Byte() = converter.Convert(doc)
        File.WriteAllBytes("webpage.pdf", pdf)
    End Sub
End Module
$vbLabelText   $csharpLabel

Podejście IronPDF:

// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
        pdf.SaveAs("webpage.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderUrlAsPdf("https://www.example.com");
        pdf.SaveAs("webpage.pdf");
    }
}
Imports IronPdf
Imports System

Class Program
    Shared Sub Main()
        Dim renderer = New ChromePdfRenderer()
        Dim pdf = renderer.RenderUrlAsPdf("https://www.example.com")
        pdf.SaveAs("webpage.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

wkhtmltopdf używa właściwości Page w ObjectSettings do określenia URL, wymagając tego samego wzorca konstrukcji dokumentu.IronPDF zapewnia dedykowaną metodę RenderUrlAsPdf(), która wyraźnie wyraża intencję.

Zapoznaj się z dokumentacją dotyczącą konwersji adresów URL do formatu PDF, aby uzyskać informacje na temat uwierzytelniania i opcji niestandardowych nagłówków.

Ustawienia niestandardowe: pliki HTML z konfiguracją strony

Konfiguracja orientacji, marginesów i rozmiaru papieru wymaga różnych podejść.

Podejście wkhtmltopdf:

// NuGet: Install-Package Haukcode.WkHtmlToPdfDotNet
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;
using System.IO;

class Program
{
    static void Main()
    {
        var converter = new SynchronizedConverter(new PdfTools());
        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Landscape,
                PaperSize = PaperKind.A4,
                Margins = new MarginSettings() { Top = 10, Bottom = 10, Left = 10, Right = 10 }
            },
            Objects = {
                new ObjectSettings()
                {
                    Page = "input.html",
                    WebSettings = { DefaultEncoding = "utf-8" }
                }
            }
        };
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("custom-output.pdf", pdf);
    }
}
// NuGet: Install-Package Haukcode.WkHtmlToPdfDotNet
using Haukcode.WkHtmlToPdfDotNet;
using Haukcode.WkHtmlToPdfDotNet.Contracts;
using System.IO;

class Program
{
    static void Main()
    {
        var converter = new SynchronizedConverter(new PdfTools());
        var doc = new HtmlToPdfDocument()
        {
            GlobalSettings = {
                ColorMode = ColorMode.Color,
                Orientation = Orientation.Landscape,
                PaperSize = PaperKind.A4,
                Margins = new MarginSettings() { Top = 10, Bottom = 10, Left = 10, Right = 10 }
            },
            Objects = {
                new ObjectSettings()
                {
                    Page = "input.html",
                    WebSettings = { DefaultEncoding = "utf-8" }
                }
            }
        };
        byte[] pdf = converter.Convert(doc);
        File.WriteAllBytes("custom-output.pdf", pdf);
    }
}
Imports Haukcode.WkHtmlToPdfDotNet
Imports Haukcode.WkHtmlToPdfDotNet.Contracts
Imports System.IO

Module Program
    Sub Main()
        Dim converter = New SynchronizedConverter(New PdfTools())
        Dim doc = New HtmlToPdfDocument() With {
            .GlobalSettings = New GlobalSettings() With {
                .ColorMode = ColorMode.Color,
                .Orientation = Orientation.Landscape,
                .PaperSize = PaperKind.A4,
                .Margins = New MarginSettings() With {.Top = 10, .Bottom = 10, .Left = 10, .Right = 10}
            },
            .Objects = {
                New ObjectSettings() With {
                    .Page = "input.html",
                    .WebSettings = New WebSettings() With {.DefaultEncoding = "utf-8"}
                }
            }
        }
        Dim pdf As Byte() = converter.Convert(doc)
        File.WriteAllBytes("custom-output.pdf", pdf)
    End Sub
End Module
$vbLabelText   $csharpLabel

Podejście IronPDF:

// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
        renderer.RenderingOptions.MarginTop = 10;
        renderer.RenderingOptions.MarginBottom = 10;
        renderer.RenderingOptions.MarginLeft = 10;
        renderer.RenderingOptions.MarginRight = 10;
        renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;

        var pdf = renderer.RenderHtmlFileAsPdf("input.html");
        pdf.SaveAs("custom-output.pdf");
    }
}
// NuGet: Install-Package IronPdf
using IronPdf;
using IronPdf.Rendering;
using System;

class Program
{
    static void Main()
    {
        var renderer = new ChromePdfRenderer();
        renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape;
        renderer.RenderingOptions.MarginTop = 10;
        renderer.RenderingOptions.MarginBottom = 10;
        renderer.RenderingOptions.MarginLeft = 10;
        renderer.RenderingOptions.MarginRight = 10;
        renderer.RenderingOptions.PaperSize = PdfPaperSize.A4;

        var pdf = renderer.RenderHtmlFileAsPdf("input.html");
        pdf.SaveAs("custom-output.pdf");
    }
}
Imports IronPdf
Imports IronPdf.Rendering
Imports System

Class Program
    Shared Sub Main()
        Dim renderer As New ChromePdfRenderer()
        renderer.RenderingOptions.PaperOrientation = PdfPaperOrientation.Landscape
        renderer.RenderingOptions.MarginTop = 10
        renderer.RenderingOptions.MarginBottom = 10
        renderer.RenderingOptions.MarginLeft = 10
        renderer.RenderingOptions.MarginRight = 10
        renderer.RenderingOptions.PaperSize = PdfPaperSize.A4

        Dim pdf = renderer.RenderHtmlFileAsPdf("input.html")
        pdf.SaveAs("custom-output.pdf")
    End Sub
End Class
$vbLabelText   $csharpLabel

wkhtmltopdf osadza ustawienia wewnątrz GlobalSettings i Objects, z MarginSettings jako osobnym obiektem.IronPDF zapewnia bezpośrednie właściwości RenderingOptions z jasnymi nazwami takimi jak PaperOrientation, MarginTop i PaperSize.

Dokumentacja API wkhtmltopdf do IronPDF

To mapowanie przyspiesza migrację, pokazując bezpośrednie odpowiedniki API:

Mapowanie CLI do IronPDF

Opcja CLI wkhtmltopdf Odpowiednik IronPDF
wkhtmltopdf input.html output.pdf renderer.RenderHtmlFileAsPdf()
wkhtmltopdf URL output.pdf renderer.RenderUrlAsPdf()
--page-size A4 RenderingOptions.PaperSize = PdfPaperSize.A4
--page-size Letter RenderingOptions.PaperSize = PdfPaperSize.Letter
--orientation Landscape RenderingOptions.PaperOrientation = Landscape
--margin-top 10mm RenderingOptions.MarginTop = 10
--margin-bottom 10mm RenderingOptions.MarginBottom = 10
--margin-left 10mm RenderingOptions.MarginLeft = 10
--margin-right 10mm RenderingOptions.MarginRight = 10
--header-html header.html RenderingOptions.HtmlHeader
--footer-center "[page]" {page} placeholder
--footer-center "[toPage]" {total-pages} placeholder
--enable-javascript Włączone domyślnie
--javascript-delay 500 RenderingOptions.WaitFor.RenderDelay = 500
--dpi 300 RenderingOptions.Dpi = 300
--grayscale RenderingOptions.GrayScale = true

Mapowanie C# Wrapper API

wkhtmltopdf Wrapper IronPDF
SynchronizedConverter ChromePdfRenderer
HtmlToPdfDocument RenderingOptions
GlobalSettings.Out pdf.SaveAs()
GlobalSettings.PaperSize RenderingOptions.PaperSize
GlobalSettings.Orientation RenderingOptions.PaperOrientation
GlobalSettings.Margins RenderingOptions.Margin*
ObjectSettings.Page RenderHtmlFileAsPdf()
ObjectSettings.HtmlContent RenderHtmlAsPdf()
converter.Convert(doc) renderer.RenderHtmlAsPdf()

Migracja składni symboli zastępczych

wkhtmltopdf Miejsce na tekst IronPDF Placeholder
[page] {page}
[toPage] {total-pages}
[date] {date}
[time] {time}
[title] {html-title}
[url] {url}

Typowe problemy związane z migracją i ich rozwiązania

Problem 1: Składnia symboli zastępczych nagłówków/stopek

wkhtmltopdf: Używa składni nawiasów kwadratowych jak [page] i [toPage].

Rozwiązanie: Zaktualizuj do symbolów zastępczych nawiasów klamrowych IronPDF:

// Before (wkhtmltopdf)
FooterSettings = { Left = "Page [page] of [toPage]" }

// After (IronPDF)
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:left;'>Page {page} of {total-pages}</div>",
    MaxHeight = 25
};
// Before (wkhtmltopdf)
FooterSettings = { Left = "Page [page] of [toPage]" }

// After (IronPDF)
renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='text-align:left;'>Page {page} of {total-pages}</div>",
    MaxHeight = 25
};
' Before (wkhtmltopdf)
FooterSettings = New With {.Left = "Page [page] of [toPage]"}

' After (IronPDF)
renderer.RenderingOptions.HtmlFooter = New HtmlHeaderFooter With {
    .HtmlFragment = "<div style='text-align:left;'>Page {page} of {total-pages}</div>",
    .MaxHeight = 25
}
$vbLabelText   $csharpLabel

Problem 2: Konfiguracja opóźnienia w JavaScript

wkhtmltopdf: Używa właściwości JavaScriptDelay z ograniczoną niezawodnością.

Rozwiązanie:IronPDF oferuje wiele opcji:

renderer.RenderingOptions.EnableJavaScript = true;

// Option 1: Fixed delay
renderer.RenderingOptions.WaitFor.RenderDelay(500);

// Option 2: Wait for specific element (more reliable)
renderer.RenderingOptions.WaitFor.HtmlElementById("content-loaded");

// Option 3: Wait for JavaScript condition
renderer.RenderingOptions.WaitFor.JavaScript("window.renderComplete === true");
renderer.RenderingOptions.EnableJavaScript = true;

// Option 1: Fixed delay
renderer.RenderingOptions.WaitFor.RenderDelay(500);

// Option 2: Wait for specific element (more reliable)
renderer.RenderingOptions.WaitFor.HtmlElementById("content-loaded");

// Option 3: Wait for JavaScript condition
renderer.RenderingOptions.WaitFor.JavaScript("window.renderComplete === true");
renderer.RenderingOptions.EnableJavaScript = True

' Option 1: Fixed delay
renderer.RenderingOptions.WaitFor.RenderDelay(500)

' Option 2: Wait for specific element (more reliable)
renderer.RenderingOptions.WaitFor.HtmlElementById("content-loaded")

' Option 3: Wait for JavaScript condition
renderer.RenderingOptions.WaitFor.JavaScript("window.renderComplete === true")
$vbLabelText   $csharpLabel

Problem 3: Nowoczesny CSS nie wyświetla się

Objaw: Układy CSS Grid i Flexbox są wyświetlane nieprawidłowo w wkhtmltopdf.

Rozwiązanie: Silnik Chromium firmy IronPDF poprawnie obsługuje nowoczesny CSS:

// This CSS now works with IronPDF
var html = @"
<style>
    .grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
    .flex { display: flex; justify-content: space-between; align-items: center; }
</style>
<div class='grid'>
    <div>Column 1</div>
    <div>Column 2</div>
    <div>Column 3</div>
</div>";

var pdf = renderer.RenderHtmlAsPdf(html);
// This CSS now works with IronPDF
var html = @"
<style>
    .grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
    .flex { display: flex; justify-content: space-between; align-items: center; }
</style>
<div class='grid'>
    <div>Column 1</div>
    <div>Column 2</div>
    <div>Column 3</div>
</div>";

var pdf = renderer.RenderHtmlAsPdf(html);
Dim html As String = "
<style>
    .grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; }
    .flex { display: flex; justify-content: space-between; align-items: center; }
</style>
<div class='grid'>
    <div>Column 1</div>
    <div>Column 2</div>
    <div>Column 3</div>
</div>"

Dim pdf = renderer.RenderHtmlAsPdf(html)
$vbLabelText   $csharpLabel

Problem 4: Renderowanie synchroniczne a asynchroniczne

wkhtmltopdf: Funkcje opakowujące są synchroniczne i blokują wątki.

Rozwiązanie:IronPDF obsługuje renderowanie asynchroniczne:

public async Task<byte[]> GeneratePdfAsync(string html)
{
    var renderer = new ChromePdfRenderer();
    var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return pdf.BinaryData;
}
public async Task<byte[]> GeneratePdfAsync(string html)
{
    var renderer = new ChromePdfRenderer();
    var pdf = await renderer.RenderHtmlAsPdfAsync(html);
    return pdf.BinaryData;
}
Imports System.Threading.Tasks

Public Async Function GeneratePdfAsync(html As String) As Task(Of Byte())
    Dim renderer As New ChromePdfRenderer()
    Dim pdf = Await renderer.RenderHtmlAsPdfAsync(html)
    Return pdf.BinaryData
End Function
$vbLabelText   $csharpLabel

Lista kontrolna migracji wkhtmltopdf

Zadania przed migracją

Przeprowadź audyt kodu źródłowego, aby zidentyfikować wszystkie przypadki użycia wkhtmltopdf:

# Find all wkhtmltopdf references
grep -r "Haukcode.WkHtmlToPdfDotNet\|WkHtmlToPdfDotNet\|DinkToPdf\|TuesPechkin\|Rotativa\|NReco.PdfGenerator" --include="*.cs" .
grep -r "wkhtmltopdf" --include="*.yml" --include="*.yaml" --include="Dockerfile" .
# Find all wkhtmltopdf references
grep -r "Haukcode.WkHtmlToPdfDotNet\|WkHtmlToPdfDotNet\|DinkToPdf\|TuesPechkin\|Rotativa\|NReco.PdfGenerator" --include="*.cs" .
grep -r "wkhtmltopdf" --include="*.yml" --include="*.yaml" --include="Dockerfile" .
SHELL

Zlokalizuj i udokumentuj pliki binarne wkhtmltopdf w celu ich usunięcia. Uwzględnij aktualne ustawienia (rozmiar papieru, marginesy, nagłówki/stopki).

Zadania związane z aktualizacją kodu

  1. Usuń wszystkie pakiety NuGet otaczające wkhtmltopdf
  2. Usuń pliki binarne wkhtmltopdf (wkhtmltopdf.exe, wkhtmltox.dll)
  3. Zainstaluj pakiet NuGet IronPDF
  4. Zaktualizuj importy przestrzeni nazw z Haukcode.WkHtmlToPdfDotNet (lub opakowanie, którego użyłeś) na IronPdf
  5. Zamień SynchronizedConverter na ChromePdfRenderer
  6. Przekształć wzorce HtmlToPdfDocument na metody bezpośredniego renderowania
  7. Zaktualizuj konfiguracje GlobalSettings na RenderingOptions
  8. Przekształć konfiguracje marginesów z MarginSettings na pojedyncze właściwości
  9. Zaktualizuj składnię placeholderów ([page]{page}, [toPage]{total-pages})
  10. Dodaj inicjalizację licencji IronPDF podczas uruchamiania

Testy po migracji

Po migracji należy zweryfikować następujące aspekty:

  • Wizualne porównanie pliku PDF (powinno wyglądać lepiej dzięki obsłudze nowoczesnego CSS)
  • Sprawdź renderowanie nowoczesnego CSS (CSS Grid i Flexbox teraz działają)
  • Testowanie stron z dużą ilością kodu JavaScript
  • Skanowanie bezpieczeństwa w celu potwierdzenia, że nie pozostały żadne pliki binarne wkhtmltopdf
  • Test obciążeniowy w celu porównania wydajności

Weryfikacja bezpieczeństwa

# Scan for any remaining wkhtmltopdf artifacts
find /var/www/ -name "*wkhtmlto*" 2>/dev/null
find /usr/local/bin/ -name "*wkhtmlto*" 2>/dev/null
docker images | grep wkhtmltopdf

# Check if any process is still using it
ps aux | grep wkhtmltopdf
# Scan for any remaining wkhtmltopdf artifacts
find /var/www/ -name "*wkhtmlto*" 2>/dev/null
find /usr/local/bin/ -name "*wkhtmlto*" 2>/dev/null
docker images | grep wkhtmltopdf

# Check if any process is still using it
ps aux | grep wkhtmltopdf
SHELL

Kluczowe korzyści z migracji do IronPDF

Przejście z wkhtmltopdf na IronPDF zapewnia kilka kluczowych korzyści:

Bezpieczeństwo: Usunięto lukę CVE-2022-35583 oraz wszystkie luki w zabezpieczeniach biblioteki wkhtmltopdf.IronPDF nie ma żadnych znanych luk CVE i regularnie otrzymuje aktualizacje zabezpieczeń.

Nowoczesny silnik renderujący:IronPDF wykorzystuje aktualny silnik Chromium, zapewniając pełną obsługę CSS3, CSS Grid, Flexbox oraz JavaScript ES6+. Nowoczesne frameworki wyświetlają się poprawnie.

Uproszczone API: Metody bezpośredniego renderowania zastępują wzorce tworzenia dokumentów. Wbudowane metody SaveAs() eliminują ręczne zarządzanie bajtami.

Rozszerzone możliwości: Manipulacja plikami PDF, podpisy cyfrowe, zgodność z PDF/A, znaki wodne oraz operacje łączenia i dzielenia to wbudowane funkcje, których wkhtmltopdf nie był w stanie zapewnić.

Aktywny rozwój: Regularne aktualizacje IronPDFśledzą bieżące wydania .NET, więc nowoczesne wersje .NET i języka C# są obsługiwane tak szybko, jak są wprowadzane.

Obsługa asynchroniczna: Zapobieganie blokowaniu wątków w aplikacjach internetowych o dużym obciążeniu dzięki natywnej obsłudze async/await.

Zwróć uwagęDinkToPdf, NReco, Rotativa, TuesPechkin oraz wkhtmltopdf są zarejestrowanymi znakami towarowymi swoich właścicieli. Ta strona nie jest powiązana, popierana ani sponsorowana przez DinkToPdf, NReco, Rotativa, TuesPechkin 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.

Curtis Chau
Autor tekstów technicznych

Curtis Chau posiada tytuł licencjata z informatyki (Uniwersytet Carleton) i specjalizuje się w front-endowym rozwoju, z ekspertką w Node.js, TypeScript, JavaScript i React. Pasjonuje się tworzeniem intuicyjnych i estetycznie przyjemnych interfejsów użytkownika, Curtis cieszy się pracą z nowoczesnymi frameworkami i tworzeniem dobrze zorganizowanych, atrakcyjnych wizualnie podrę...

Czytaj więcej

Zespół wsparcia Iron

Jesteśmy online 24 godziny, 5 dni w tygodniu.
Czat
E-mail
Zadzwoń do mnie