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"/>
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.
Krok 2: Zainstaluj IronPDF
# Add IronPDF(secure, modern alternative)
dotnet add package IronPdf
# Add IronPDF(secure, modern alternative)
dotnet add package IronPdf
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
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"
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
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
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
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
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
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
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
}
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")
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)
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
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" .
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
- Usuń wszystkie pakiety NuGet otaczające wkhtmltopdf
- Usuń pliki binarne wkhtmltopdf (wkhtmltopdf.exe, wkhtmltox.dll)
- Zainstaluj pakiet NuGet IronPDF
- Zaktualizuj importy przestrzeni nazw z
Haukcode.WkHtmlToPdfDotNet(lub opakowanie, którego użyłeś) naIronPdf - Zamień
SynchronizedConverternaChromePdfRenderer - Przekształć wzorce
HtmlToPdfDocumentna metody bezpośredniego renderowania - Zaktualizuj konfiguracje
GlobalSettingsnaRenderingOptions - Przekształć konfiguracje marginesów z
MarginSettingsna pojedyncze właściwości - Zaktualizuj składnię placeholderów (
[page]→{page},[toPage]→{total-pages}) - 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
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.

