Jak konwertować elementy HTML i fragmenty stron do formatu PDF w języku C
IronPDF nie posiada wbudowanej metody SelectElement lub SelectCss do celowania w konkretne elementy HTML. ChromePdfRenderer renderuje kompletne dokumenty HTML — pełną stronę, pełny URL, pełny ciąg HTML. Aby utworzyć plik PDF z określonej sekcji strony, izolujemy docelowy element przed renderowaniem, stosując jedną z czterech metod: manipulację DOM za pomocą JavaScript, wstrzykiwanie CSS, ekstrakcję fragmentów HTML po stronie serwera lub renderowanie adresów URL z wykorzystaniem JS.
Każde podejście odpowiada innym ograniczeniom. Izolacja DOM w JavaScript działa podczas renderowania adresów URL lub całych stron, gdzie musimy usunąć wszystko oprócz elementu docelowego. Wstrzykiwanie CSS ukrywa niepożądaną treść bez zmiany struktury DOM. Pobieranie danych po stronie serwera zapewnia najczystszy wynik, gdy mamy dostęp do surowego kodu HTML. Renderowanie adresów URL z wykorzystaniem JS obsługuje interaktywne pulpity nawigacyjne oraz strony zewnętrzne, w przypadku których źródłowy kod HTML nie jest dostępny.
Rozpocznij bezpłatny 30-dniowy okres probny, aby przetestować wszystkie cztery podejścia.
Szybki start: Wyodrębnij określony element HTML jako plik PDF
Celuj w dowolny element za pomocą selektora CSS, używając izolacji JavaScript DOM i WaitFor, a następnie renderuj tylko ten fragment do PDF.
-
Install IronPDF with NuGet Package Manager
PM > Install-Package IronPdf -
Skopiuj i uruchom ten fragment kodu.
using IronPdf; var renderer = new ChromePdfRenderer(); renderer.RenderingOptions.EnableJavaScript = true; renderer.RenderingOptions.JavaScript = @" var target = document.querySelector('#invoice-summary'); document.body.innerHTML = target.outerHTML; "; renderer.RenderingOptions.WaitFor.HtmlQuerySelector("#invoice-summary", 10000); var pdf = renderer.RenderHtmlAsPdf(fullPageHtml); pdf.SaveAs("invoice-summary.pdf"); -
Wdrożenie do testowania w środowisku produkcyjnym
Rozpocznij używanie IronPDF w swoim projekcie już dziś z darmową wersją próbną
Minimalny przebieg pracy (3 kroki)
- Zainstaluj IronPDF korzystając z NuGet:
Install-Package IronPdf - Skonfiguruj
ChromePdfRenderOptions.JavaScript, aby wyizolować docelowy element iWaitFor, aby upewnić się, że on istnieje. - Wywołaj
RenderHtmlAsPdf()lubRenderUrlAsPdf()— PDF zawiera tylko odizolowaną treść.
Jak wyodrębnić elementy za pomocą manipulacji DOM w JavaScript?
ChromePdfRenderOptions.JavaScript akceptuje ciąg JavaScript, który jest uruchamiany po załadowaniu HTML, ale przed rendowaniem PDF. Zastępując document.body.innerHTML za outerHTML docelowego elementu, usuwamy wszystko inne z renderowanej strony. To najbardziej wszechstronne podejście — działa zarówno z RenderHtmlAsPdf(), jak i z RenderUrlAsPdf().
WaitFor.HtmlQuerySelector() upewnia się, że element docelowy istnieje w DOM, zanim JavaScript się uruchomi. Ma to kluczowe znaczenie w przypadku stron z treścią asynchroniczną — komponentów React, szablonów Angular lub danych opartych na API, które wyświetlają się po początkowym załadowaniu strony.
using IronPdf;
string fullPageHtml = @"
<html>
<body>
<header><h1>Acme Corp Invoice</h1></header>
<nav>Navigation links...</nav>
<div id='invoice-summary'>
<h2>Invoice #12345</h2>
<table>
<tr><td>Widget A</td><td>$49.99</td></tr>
<tr><td>Widget B</td><td>$29.99</td></tr>
<tr><td><strong>Total</strong></td><td><strong>$79.98</strong></td></tr>
</table>
</div>
<footer>Footer content...</footer>
</body>
</html>";
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;
// Replace the body with only the target element
renderer.RenderingOptions.JavaScript = @"
var el = document.querySelector('#invoice-summary');
if (el) {
document.body.innerHTML = el.outerHTML;
}
";
// Wait for the target element to exist before JS executes
renderer.RenderingOptions.WaitFor.HtmlQuerySelector("#invoice-summary", 10000);
PdfDocument pdf = renderer.RenderHtmlAsPdf(fullPageHtml);
pdf.SaveAs("invoice-summary-only.pdf");
using IronPdf;
string fullPageHtml = @"
<html>
<body>
<header><h1>Acme Corp Invoice</h1></header>
<nav>Navigation links...</nav>
<div id='invoice-summary'>
<h2>Invoice #12345</h2>
<table>
<tr><td>Widget A</td><td>$49.99</td></tr>
<tr><td>Widget B</td><td>$29.99</td></tr>
<tr><td><strong>Total</strong></td><td><strong>$79.98</strong></td></tr>
</table>
</div>
<footer>Footer content...</footer>
</body>
</html>";
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;
// Replace the body with only the target element
renderer.RenderingOptions.JavaScript = @"
var el = document.querySelector('#invoice-summary');
if (el) {
document.body.innerHTML = el.outerHTML;
}
";
// Wait for the target element to exist before JS executes
renderer.RenderingOptions.WaitFor.HtmlQuerySelector("#invoice-summary", 10000);
PdfDocument pdf = renderer.RenderHtmlAsPdf(fullPageHtml);
pdf.SaveAs("invoice-summary-only.pdf");
Imports IronPdf
Dim fullPageHtml As String = "
<html>
<body>
<header><h1>Acme Corp Invoice</h1></header>
<nav>Navigation links...</nav>
<div id='invoice-summary'>
<h2>Invoice #12345</h2>
<table>
<tr><td>Widget A</td><td>$49.99</td></tr>
<tr><td>Widget B</td><td>$29.99</td></tr>
<tr><td><strong>Total</strong></td><td><strong>$79.98</strong></td></tr>
</table>
</div>
<footer>Footer content...</footer>
</body>
</html>"
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.EnableJavaScript = True
' Replace the body with only the target element
renderer.RenderingOptions.JavaScript = "
var el = document.querySelector('#invoice-summary');
if (el) {
document.body.innerHTML = el.outerHTML;
}
"
' Wait for the target element to exist before JS executes
renderer.RenderingOptions.WaitFor.HtmlQuerySelector("#invoice-summary", 10000)
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(fullPageHtml)
pdf.SaveAs("invoice-summary-only.pdf")
JavaScript zastępuje całe body za pomocą #invoice-summary div's outerHTML. Powstały plik PDF zawiera wyłącznie tabelę z fakturą — bez nagłówka, nawigacji ani stopki. WaitFor.HtmlElementById() zapewnia prostszą alternatywę przy celowaniu według ID:
// Alternative: wait by ID directly
renderer.RenderingOptions.WaitFor.HtmlElementById("invoice-summary", 10000);
// Alternative: wait by ID directly
renderer.RenderingOptions.WaitFor.HtmlElementById("invoice-summary", 10000);
' Alternative: wait by ID directly
renderer.RenderingOptions.WaitFor.HtmlElementById("invoice-summary", 10000)
Dla złożonych selektorów (nazwy klas, atrybuty danych, zagnieżdżone elementy), HtmlQuerySelector() akceptuje dowolny prawidłowy ciąg selektora CSS, który document.querySelector() by zaakceptował. Dodatkowe WaitFor metody ułatwiające obejmują HtmlElementByClassName(), HtmlElementByName(), i HtmlElementByTagName() — każda wewnętrznie deleguje do HtmlQuerySelector(), ale zapewnia jaśniejszy zamiar w kodzie.
Gdy element docelowy zależy od dziedziczonych stylów od nadrzędnych kontenerów, outerHTML może utracić reguły CSS, które polegają na selektorach przodków (np. .dashboard .widget table { ... }. Aby je zachować, skopiuj odpowiednie <style> i <link> tagi z <head> do izolacji JS:
renderer.RenderingOptions.JavaScript = @"
var el = document.querySelector('#invoice-summary');
if (el) {
var head = document.head.innerHTML;
document.body.innerHTML = el.outerHTML;
document.head.innerHTML = head;
}
";
renderer.RenderingOptions.JavaScript = @"
var el = document.querySelector('#invoice-summary');
if (el) {
var head = document.head.innerHTML;
document.body.innerHTML = el.outerHTML;
document.head.innerHTML = head;
}
";
renderer.RenderingOptions.JavaScript = "
var el = document.querySelector('#invoice-summary');
if (el) {
var head = document.head.innerHTML;
document.body.innerHTML = el.outerHTML;
document.head.innerHTML = head;
}
"
To zachowuje oryginalną <head> treść (arkusze stylów, czcionki, metatagi) przy jednoczesnym zastępowaniu jedynie body. JavaScript to PDF how-to i WaitFor how-to obejmują dodatkowe opcje konfiguracji, w tym NetworkIdle0() dla stron z wieloma asynchronicznymi źródłami danych.
Jak wyodrębnić elementy za pomocą wstrzykiwania CSS?
ChromePdfRenderOptions.CustomCssUrl akceptuje ścieżkę do pliku lub URL do arkusza stylów, który IronPDF stosuje przed renderowaniem. Zamiast manipulować DOM, ukrywamy wszystko poza docelowym elementem przy użyciu CSS display: none. Pozwala to zachować oryginalną strukturę DOM i całkowicie uniknąć wykonywania kodu JavaScript.
using IronPdf;
// Create a CSS file that hides everything except #invoice-summary
string cssContent = @"
body > *:not(#invoice-summary) {
display: none !important;
}
#invoice-summary {
display: block !important;
margin: 0;
padding: 20px;
}
";
File.WriteAllText("isolate-element.css", cssContent);
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CustomCssUrl = "isolate-element.css";
PdfDocument pdf = renderer.RenderHtmlAsPdf(fullPageHtml);
pdf.SaveAs("invoice-css-isolated.pdf");
using IronPdf;
// Create a CSS file that hides everything except #invoice-summary
string cssContent = @"
body > *:not(#invoice-summary) {
display: none !important;
}
#invoice-summary {
display: block !important;
margin: 0;
padding: 20px;
}
";
File.WriteAllText("isolate-element.css", cssContent);
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.CustomCssUrl = "isolate-element.css";
PdfDocument pdf = renderer.RenderHtmlAsPdf(fullPageHtml);
pdf.SaveAs("invoice-css-isolated.pdf");
Imports IronPdf
Imports System.IO
' Create a CSS file that hides everything except #invoice-summary
Dim cssContent As String = "
body > *:not(#invoice-summary) {
display: none !important;
}
#invoice-summary {
display: block !important;
margin: 0;
padding: 20px;
}
"
File.WriteAllText("isolate-element.css", cssContent)
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.CustomCssUrl = "isolate-element.css"
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(fullPageHtml)
pdf.SaveAs("invoice-css-isolated.pdf")
Uwaga: CustomCssUrl działa tylko z RenderHtmlAsPdf() podczas rendowania z ciągów HTML. Dla renderowania URL, osadź wstrzyknięcie CSS w JavaScript.
renderer.RenderingOptions.JavaScript = @"
var style = document.createElement('style');
style.textContent = 'body > *:not(#invoice-summary) { display: none !important; }';
document.head.appendChild(style);
";
renderer.RenderingOptions.JavaScript = @"
var style = document.createElement('style');
style.textContent = 'body > *:not(#invoice-summary) { display: none !important; }';
document.head.appendChild(style);
";
renderer.RenderingOptions.JavaScript = "
var style = document.createElement('style');
style.textContent = 'body > *:not(#invoice-summary) { display: none !important; }';
document.head.appendChild(style);
"
Kiedy kontrolujemy źródłowy HTML, @media print reguły oferują najlżejszą alternatywę — bez zewnętrznych zależności, bez iniekcji podczas działania:
@media print {
header, nav, footer, .sidebar { display: none !important; }
#invoice-summary { width: 100%; margin: 0; }
}
Ustaw CssMediaType na PdfCssMediaType.Print na rendererze, aby aktywować te reguły:
renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;
renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print;
renderer.RenderingOptions.CssMediaType = IronPdf.Rendering.PdfCssMediaType.Print
Jest to idealne rozwiązanie w scenariuszach drukowania sekcji formularzy, w których aplikacja już definiuje układy przeznaczone do druku. Formularze zgłoszenia ubezpieczeniowego, wieloetapowe kreatory i podsumowania zakupów często używają @media print reguł do ukrywania nawigacji i wskaźników postępu podczas rozszerzania odpowiedniej sekcji zawartości.
Podejście CSS ma jedno ważne ograniczenie: ukryte elementy nadal zajmują miejsce w przepływie dokumentu, jeśli display: none jest używany na niewłaściwym poziomie szczegółowości. Zawsze używaj !important, aby nadpisać style frameworka (Bootstrap, Tailwind), które mogą ponownie wyświetlić elementy na pewnych punktach przełamania. W przypadku głęboko zagnieżdżonych elementów docelowych bardziej precyzyjny selektor pozwala uniknąć ukrycia elementów pobocznych:
body > *:not(#target),
body > *:not(#target) ~ * {
display: none !important;
}
Jak wyodrębnić fragmenty HTML po stronie serwera?
Gdy mamy dostęp do surowego HTML — odczytując go z pliku, bazy danych, CMS czy odpowiedzi HTTP — najczystsze podejście to wyodrębnienie docelowego elementu po stronie serwera za pomocą parsera HTML, następnie przekazanie fragmentu do RenderHtmlAsPdf(). Bez JavaScriptu, bez wstrzykiwania CSS, bez manipulacji DOM w czasie wykonywania.
AngleSharp jest standardowym parserem HTML dla platformy .NET Standard przeznaczonym do tego wzorca:
using IronPdf;
using AngleSharp;
using AngleSharp.Html.Parser;
string fullPageHtml = @"
<html>
<head>
<style>
table { border-collapse: collapse; width: 100%; }
td, th { border: 1px solid #ddd; padding: 8px; text-align: left; }
</style>
</head>
<body>
<header><h1>Dashboard</h1></header>
<div id='revenue-widget'>
<h3>Q4 Revenue</h3>
<table>
<tr><th>Month</th><th>Revenue</th></tr>
<tr><td>October</td><td>$1.2M</td></tr>
<tr><td>November</td><td>$1.5M</td></tr>
<tr><td>December</td><td>$1.8M</td></tr>
</table>
</div>
<div id='other-content'>Other widgets...</div>
</body>
</html>";
// Parse and extract the target element
var parser = new HtmlParser();
var document = parser.ParseDocument(fullPageHtml);
var targetElement = document.QuerySelector("#revenue-widget");
if (targetElement is null)
{
Console.WriteLine("Target element not found.");
return;
}
// Wrap the fragment in a minimal HTML document to preserve styles
string fragmentHtml = $@"
<html>
<head>
<style>
table {{ border-collapse: collapse; width: 100%; }}
td, th {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
</style>
</head>
<body>
{targetElement.OuterHtml}
</body>
</html>";
var renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf(fragmentHtml);
pdf.SaveAs("revenue-widget.pdf");
using IronPdf;
using AngleSharp;
using AngleSharp.Html.Parser;
string fullPageHtml = @"
<html>
<head>
<style>
table { border-collapse: collapse; width: 100%; }
td, th { border: 1px solid #ddd; padding: 8px; text-align: left; }
</style>
</head>
<body>
<header><h1>Dashboard</h1></header>
<div id='revenue-widget'>
<h3>Q4 Revenue</h3>
<table>
<tr><th>Month</th><th>Revenue</th></tr>
<tr><td>October</td><td>$1.2M</td></tr>
<tr><td>November</td><td>$1.5M</td></tr>
<tr><td>December</td><td>$1.8M</td></tr>
</table>
</div>
<div id='other-content'>Other widgets...</div>
</body>
</html>";
// Parse and extract the target element
var parser = new HtmlParser();
var document = parser.ParseDocument(fullPageHtml);
var targetElement = document.QuerySelector("#revenue-widget");
if (targetElement is null)
{
Console.WriteLine("Target element not found.");
return;
}
// Wrap the fragment in a minimal HTML document to preserve styles
string fragmentHtml = $@"
<html>
<head>
<style>
table {{ border-collapse: collapse; width: 100%; }}
td, th {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
</style>
</head>
<body>
{targetElement.OuterHtml}
</body>
</html>";
var renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf(fragmentHtml);
pdf.SaveAs("revenue-widget.pdf");
Imports IronPdf
Imports AngleSharp
Imports AngleSharp.Html.Parser
Dim fullPageHtml As String = "
<html>
<head>
<style>
table { border-collapse: collapse; width: 100%; }
td, th { border: 1px solid #ddd; padding: 8px; text-align: left; }
</style>
</head>
<body>
<header><h1>Dashboard</h1></header>
<div id='revenue-widget'>
<h3>Q4 Revenue</h3>
<table>
<tr><th>Month</th><th>Revenue</th></tr>
<tr><td>October</td><td>$1.2M</td></tr>
<tr><td>November</td><td>$1.5M</td></tr>
<tr><td>December</td><td>$1.8M</td></tr>
</table>
</div>
<div id='other-content'>Other widgets...</div>
</body>
</html>"
' Parse and extract the target element
Dim parser As New HtmlParser()
Dim document = parser.ParseDocument(fullPageHtml)
Dim targetElement = document.QuerySelector("#revenue-widget")
If targetElement Is Nothing Then
Console.WriteLine("Target element not found.")
Return
End If
' Wrap the fragment in a minimal HTML document to preserve styles
Dim fragmentHtml As String = $"
<html>
<head>
<style>
table {{ border-collapse: collapse; width: 100%; }}
td, th {{ border: 1px solid #ddd; padding: 8px; text-align: left; }}
</style>
</head>
<body>
{targetElement.OuterHtml}
</body>
</html>"
Dim renderer As New ChromePdfRenderer()
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(fragmentHtml)
pdf.SaveAs("revenue-widget.pdf")
Kluczowym szczegółem jest opakowanie wyodrębnionego fragmentu w kompletne dokument HTML z odpowiednimi <style> lub <link> tagami. Bez tej nakładki style wbudowane renderują się poprawnie, ale zewnętrzne arkusze stylów i odziedziczone reguły CSS są tracone. W przypadku renderowania podglądu szablonu wiadomości e-mail — gdzie kod HTML szablonu jest już zapisany jako ciąg znaków — ten wzorzec ekstrakcji zapewnia wyniki idealne pod względem pikseli, ponieważ kontrolujemy każdy aspekt renderowanej treści.
Ten sam schemat działa z HtmlAgilityPack jako alternatywnym parserem:
using HtmlAgilityPack;
using IronPdf;
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(fullPageHtml);
var targetNode = htmlDoc.DocumentNode.SelectSingleNode("//*[@id='revenue-widget']");
if (targetNode is null)
{
Console.WriteLine("Target element not found.");
return;
}
string fragmentHtml = $"<html><body>{targetNode.OuterHtml}</body></html>";
var renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf(fragmentHtml);
pdf.SaveAs("revenue-widget-hap.pdf");
using HtmlAgilityPack;
using IronPdf;
var htmlDoc = new HtmlDocument();
htmlDoc.LoadHtml(fullPageHtml);
var targetNode = htmlDoc.DocumentNode.SelectSingleNode("//*[@id='revenue-widget']");
if (targetNode is null)
{
Console.WriteLine("Target element not found.");
return;
}
string fragmentHtml = $"<html><body>{targetNode.OuterHtml}</body></html>";
var renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf(fragmentHtml);
pdf.SaveAs("revenue-widget-hap.pdf");
Imports HtmlAgilityPack
Imports IronPdf
Dim htmlDoc As New HtmlDocument()
htmlDoc.LoadHtml(fullPageHtml)
Dim targetNode = htmlDoc.DocumentNode.SelectSingleNode("//*[@id='revenue-widget']")
If targetNode Is Nothing Then
Console.WriteLine("Target element not found.")
Return
End If
Dim fragmentHtml As String = $"<html><body>{targetNode.OuterHtml}</body></html>"
Dim renderer As New ChromePdfRenderer()
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(fragmentHtml)
pdf.SaveAs("revenue-widget-hap.pdf")
Wybór między AngleSharp a HtmlAgilityPack jest w dużej mierze kwestią preferencji. AngleSharp używa selektorów CSS (QuerySelector), co jest zgodne z modeli mentalnymi dewelopera frontend. HtmlAgilityPack używa XPath (SelectSingleNode), który jest bardziej znany w kodach .NET z dużym naciskiem na XML.
W przypadku renderowania podglądu szablonów wiadomości e-mail — gdzie kod HTML szablonu jest przechowywany jako ciąg znaków w bazie danych lub systemie CMS — ekstrakcja po stronie serwera zapewnia wyniki idealne pod względem pikseli, ponieważ kontrolujemy każdy aspekt renderowanej treści. Możemy również używać RenderHtmlAsPdf(string Html, string BaseUrlOrPath) z drugim parametrem wskazującym na lokalny katalog zasobów, aby zapewnić prawidłowe rozwiązywanie ścieżek obrazów i arkuszy stylów.
PdfDocument pdf = renderer.RenderHtmlAsPdf(fragmentHtml, @"C:\templates\assets\");
PdfDocument pdf = renderer.RenderHtmlAsPdf(fragmentHtml, @"C:\templates\assets\");
Dim pdf As PdfDocument = renderer.RenderHtmlAsPdf(fragmentHtml, "C:\templates\assets\")
Wadą w porównaniu z izolacją DOM w JavaScript jest to, że ekstrakcja po stronie serwera nie obsługuje treści wymagających renderowania po stronie klienta (elementy generowane przez JavaScript, komponenty SPA, dane pobierane przez API). Jeśli HTML zawiera <div id="app"></div>, które aplikacja React lub Vue wypełnia podczas działania, wyodrębniony fragment będzie pusty. W takich przypadkach należy zastosować podejście 1 lub 4.
Jak wskazywać docelowe elementy podczas renderowania aktywnych adresów URL?
Dla żywych URL, gdzie nie możemy uzyskać dostępu do źródłowego HTML — zewnętrzne pulpity nawigacyjne, zewnętrzne raporty, hostowane aplikacje — łączymy RenderUrlAsPdf() z JavaScript i WaitFor, aby wyizolować określoną sekcję po załadowaniu strony.
Oto scenariusz eksportu widżetu pulpitu nawigacyjnego: narzędzie BI wyświetla wykresy i tabele na stronie internetowej, a my musimy wyeksportować pojedynczy widżet jako plik PDF w celu dystrybucji wśród interesariuszy.
using IronPdf;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;
// Wait for the dashboard widget to render (async content)
renderer.RenderingOptions.WaitFor.HtmlQuerySelector("[data-widget='revenue-chart']", 15000);
// Isolate the widget after it renders
renderer.RenderingOptions.JavaScript = @"
var widget = document.querySelector('[data-widget=""revenue-chart""]');
if (widget) {
// Preserve computed styles by cloning into a clean body
document.body.innerHTML = '';
document.body.appendChild(widget);
}
";
PdfDocument pdf = renderer.RenderUrlAsPdf("https://dashboard.example.com/q4-report");
pdf.SaveAs("revenue-chart-export.pdf");
using IronPdf;
var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.EnableJavaScript = true;
// Wait for the dashboard widget to render (async content)
renderer.RenderingOptions.WaitFor.HtmlQuerySelector("[data-widget='revenue-chart']", 15000);
// Isolate the widget after it renders
renderer.RenderingOptions.JavaScript = @"
var widget = document.querySelector('[data-widget=""revenue-chart""]');
if (widget) {
// Preserve computed styles by cloning into a clean body
document.body.innerHTML = '';
document.body.appendChild(widget);
}
";
PdfDocument pdf = renderer.RenderUrlAsPdf("https://dashboard.example.com/q4-report");
pdf.SaveAs("revenue-chart-export.pdf");
Imports IronPdf
Dim renderer As New ChromePdfRenderer()
renderer.RenderingOptions.EnableJavaScript = True
' Wait for the dashboard widget to render (async content)
renderer.RenderingOptions.WaitFor.HtmlQuerySelector("[data-widget='revenue-chart']", 15000)
' Isolate the widget after it renders
renderer.RenderingOptions.JavaScript = "
var widget = document.querySelector('[data-widget=""revenue-chart""]);
if (widget) {
// Preserve computed styles by cloning into a clean body
document.body.innerHTML = '';
document.body.appendChild(widget);
}
"
Dim pdf As PdfDocument = renderer.RenderUrlAsPdf("https://dashboard.example.com/q4-report")
pdf.SaveAs("revenue-chart-export.pdf")
WaitFor.HtmlQuerySelector() zapewnia, że widget istnieje w DOM, zanim JavaScript się uruchomi. Limit czasu wynoszący 15 sekund uwzględnia wolniejsze wywołania API, które wypełniają dane na pulpicie nawigacyjnym. Następnie JavaScript redukuje stronę do samego widgetu.
Dla stron z złożonymi zależnościami CSS, podejście appendChild (przenoszenie węzła, a nie kopiowanie jego outerHTML) zachowuje więcej obliczonych stylów, ponieważ element zachowuje swoją pozycję w CSSOM. Podejście zastąpienia innerHTML z podejścia 1 jest prostsze, ale może utracić style zależne od selektorów przodków.
Gdy docelowa strona wymaga uwierzytelnienia, skonfiguruj ciasteczka na rendererze przed wywołaniem RenderUrlAsPdf():
renderer.RenderingOptions.CustomCookies = new Dictionary<string, string>
{
{ "session_id", "abc123" },
{ "auth_token", "bearer-xyz" }
};
renderer.RenderingOptions.CustomCookies = new Dictionary<string, string>
{
{ "session_id", "abc123" },
{ "auth_token", "bearer-xyz" }
};
Imports System.Collections.Generic
renderer.RenderingOptions.CustomCookies = New Dictionary(Of String, String) From {
{"session_id", "abc123"},
{"auth_token", "bearer-xyz"}
}
WaitFor oferuje dodatkowe strategie oczekiwania poza HtmlQuerySelector(). NetworkIdle0() czeka, aż wszystkie żądania sieciowe zakończą się z zerową liczbą oczekujących połączeń — użyteczne dla pulpitów nawigacyjnych, które ładują dane z wielu punktów końcowych API. NetworkIdle2() toleruje do dwóch oczekujących połączeń, co obsługuje strony z trwałymi połączeniami WebSocket lub długim ładowaniem. JavaScript() czeka, aż strona wywoła window.ironpdf.notifyRender() — najbardziej precyzyjna opcja, gdy kontrolujemy docelową stronę i możemy sygnalizować gotowość do renderowania po załadowaniu wszystkich danych i zakończeniu animacji.
W przypadku powtarzających się eksportów z pulpitu nawigacyjnego (np. generowanie plików PDF co noc w celu rozesłania ich pocztą elektroniczną do interesariuszy) należy umieścić renderowanie w pętli ponownych prób, która przechwytuje wyjątki związane z przekroczeniem limitu czasu. Jeśli WaitFor przekracza swoją maxWaitTime, IronPDF przystępuje do renderowania dostępnej treści — może być ona niekompletna. Zwiększenie czasu oczekiwania lub przejście na NetworkIdle0() zazwyczaj rozwiązuje przypadkowe awarie na wolniejszych sieciach.
Porównanie wszystkich czterech podejść
| Podejście | Najlepsze dla | Wymagany kod źródłowy HTML | Zależność JS | Złożoność |
|---|---|---|---|---|
| Izolacja DOM w JavaScript | Powszechne wyodrębnianie elementów z dowolnego źródła | Nie | Tak | Medium |
| Wstrzykiwanie CSS | Ukrywanie sekcji bez zmian w DOM; @media print układy |
Częściowe (CustomCssUrl wymaga RenderHtmlAsPdf) | Nie (chyba że wstawianie odbywa się za pomocą JS dla adresów URL) | Low |
| Wyodrębnianie fragmentów po stronie serwera | Treści CMS, zapisane szablony, podglądy wiadomości e-mail | Tak | Nie | Niski–Średni |
| Renderowanie adresów URL z wykorzystaniem JS Targeting | Aktywne pulpity nawigacyjne, strony zewnętrzne, widżety SPA | Nie | Tak | Średni–wysoki |
Wybór właściwego podejścia
Decyzja zależy od dwóch czynników: czy mamy dostęp do surowego kodu HTML oraz czy renderowanie treści docelowej wymaga użycia JavaScript.
Najczęstszym przypadkiem użycia jest wyodrębnianie pozycji z faktur. Gdy kod HTML faktury jest generowany po stronie serwera (widoki Razor, szablony Handlebars, zapisane ciągi HTML), podejście 3 (pobieranie po stronie serwera) zapewnia najczystszy wynik bez obciążenia środowiska uruchomieniowego. Wyodrębnij #line-items tabelę, owiń ją w stylową otoczkę HTML i renderuj.
Eksport widżetu pulpitu nawigacyjnego wymaga wykonania kodu JavaScript, ponieważ zawartość widżetu jest wypełniana przez wywołania API po początkowym załadowaniu strony. Podejście 1 (izolacja JS DOM) radzi sobie z tym, gdy pulpit nawigacyjny działa lokalnie lub za uwierzytelnieniem. Podejście 4 (renderowanie adresów URL z wykorzystaniem JS) jest konieczne, gdy pulpit nawigacyjny jest aplikacją hostowaną przez stronę trzecią, w przypadku której dysponujemy jedynie adresem URL.
Wydruk sekcji formularza — wyodrębnienie konkretnej sekcji formularza wieloetapowego do przeglądu przez użytkownika lub archiwizacji dla zgodności — naturalnie mapuje się na Podejście 2 (iniekcja CSS), gdy aplikacja już definiuje @media print reguły, lub na Podejście 3, gdy HTML formularza jest solidowany po stronie serwera.
Renderowanie podglądu szablonu wiadomości e-mail — generowanie podglądu PDF szablonu wiadomości e-mail w formacie HTML przed wysłaniem — jest scenariuszem typowym dla podejścia 3. Szablon HTML to zapisany ciąg, zewnętrzne zasoby (obrazy, czcionki) są hostowane pod znanymi URL, a parameter BaseUrlOrPath na RenderHtmlAsPdf() rozwiązuje wszystkie względne ścieżki.
W przypadku aplikacji, które muszą obsługiwać wiele scenariuszy, należy zamknąć logikę renderowania w interfejsie usługi, który akceptuje parametr strategii:
public enum ElementExtractionStrategy
{
JavaScriptIsolation,
CssInjection,
ServerSideExtraction,
UrlWithJsTargeting
}
public enum ElementExtractionStrategy
{
JavaScriptIsolation,
CssInjection,
ServerSideExtraction,
UrlWithJsTargeting
}
Public Enum ElementExtractionStrategy
JavaScriptIsolation
CssInjection
ServerSideExtraction
UrlWithJsTargeting
End Enum
Dzięki temu kod wywołujący może wybrać odpowiednie podejście w oparciu o typ danych wejściowych bez konieczności powielania konfiguracji renderera.
Kolejne kroki
Izolacja elementów HTML w IronPDF jest kwestią dotyczącą renderowania, a nie wbudowaną funkcją API. Powyższe cztery podejścia obejmują pełne spektrum — od ekstrakcji szablonów po stronie serwera (zero JS, najczystszy wynik) po kierowanie na aktywne adresy URL (pełne wykonanie JS, obsługa aplikacji SPA i treści asynchronicznych). Tabela porównawcza stanowi skrócone źródło informacji, a scenariusze z życia wzięte odnoszą typowe wymagania biznesowe do odpowiedniej strategii.
Kilka dodatkowych uwag dotyczących wdrożeń produkcyjnych:
Wydajność: Pobieranie po stronie serwera (podejście 3) jest najszybsze, ponieważ całkowicie pomija wykonanie kodu JavaScript. Podejścia oparte na JavaScript (1 i 4) dodają nakład czasowy proporcjonalny do złożoności strony i czasu WaitFor. Dla przetwarzania wsadowego (np. generowanie 500 faktur PDF), wyodrębnianie po stronie serwera z Parallel.ForEach i wieloma instancjami ChromePdfRenderer zapewnia najlepszą przepustowość.
Debugowanie: Gdy wyjście PDF jest puste lub brakuje treści, włącz EnableJavaScript = true i zwiększ czas oczekiwania WaitFor. Jeśli element docelowy zależy od asynchronicznych danych, WaitFor.NetworkIdle0() jest bardziej niezawodne niż stałe RenderDelay. Przewodnik po opcjach renderowania obejmuje konfiguracje szerokości okna wyświetlania i dopasowania do papieru, które mają wpływ na układ.
Łączenie podejść: Nic nie stoi na przeszkodzie, aby łączyć strategie. Możemy użyć ekstrakcji po stronie serwera, aby zbudować złożony dokument HTML z wielu fragmentów (nagłówek z jednego źródła, tabela danych z innego, wykres SVG z trzeciego), a następnie wyrenderować złożony dokument jako pojedynczy plik PDF. RenderHtmlAsPdf(string Html, string BaseUrlOrPath) rozwiązuje względne ścieżki zasobów z podstawowego URL, co ułatwia składanie dokumentów z różnorodnych źródeł.
Przeglądaj JavaScript to PDF how-to dla zaawansowanych wzorców wykonania JS, dokumentację WaitFor dla wszystkich dostępnych strategii oczekiwania, przewodnik po opcjach renderingu dla kompletnej powierzchni ChromePdfRenderOptions, i przykład kodu niestandardowego JavaScript dla gotowych do uruchomienia fragmentów.
Zobacz opcje licencji począwszy od 749 USD. ChromePdfRenderOptions specyfikacja API i WaitFor specyfikacja API dokumentuje każdą właściwość i metodę.
Często Zadawane Pytania
Jakie są główne metody konwersji elementów HTML do formatu PDF w języku C#?
Główne podejścia obejmują izolację JS, ukrywanie CSS, ekstrakcję po stronie serwera oraz kierowanie na aktywne adresy URL, a wszystkie one mogą być wdrożone przy użyciu IronPDF.
Jak działa izolacja JS w kontekście konwersji HTML do PDF?
Izolacja JS polega na uruchomieniu kodu JavaScript w celu dynamicznej manipulacji dokumentem HTML przed konwersją do formatu PDF. Można to osiągnąć za pomocą IronPDF, aby zapewnić renderowanie tylko określonych elementów.
Czym jest ukrywanie CSS i jak wykorzystuje się je podczas konwersji plików PDF?
Ukrywanie za pomocą CSS polega na użyciu stylów CSS do ukrycia elementów, które nie powinny pojawiać się w pliku PDF. IronPDF obsługuje tę funkcję, umożliwiając programistom określenie arkuszy stylów lub reguł stylów podczas procesu konwersji.
Czy IronPDF może wyodrębniać określone elementy HTML po stronie serwera w celu generowania plików PDF?
Tak, IronPDF może wyodrębniać określone elementy HTML po stronie serwera, co pozwala na precyzyjną kontrolę nad tym, które części strony internetowej są konwertowane do formatu PDF.
Jaka jest zaleta kierowania na aktywne adresy URL podczas konwersji HTML do PDF?
Funkcja Live URL targeting pozwala IronPDF konwertować elementy z aktywnego adresu URL strony internetowej bezpośrednio do formatu PDF, zapewniając przechwycenie najbardziej aktualnej treści bez konieczności korzystania z lokalnych plików HTML.
Czy za pomocą IronPDF można przekonwertować tylko część strony internetowej do formatu PDF?
Tak, IronPDF oferuje funkcję konwersji określonych sekcji lub elementów strony internetowej do formatu PDF, co ułatwia skupienie się na istotnych treściach.
W jaki sposób IronPDF radzi sobie z treścią dynamiczną podczas konwersji HTML do PDF?
IronPDF może renderować treści dynamiczne poprzez wykonywanie kodu JavaScript podczas konwersji, zapewniając, że elementy oparte na skryptach po stronie klienta są dokładnie odwzorowane w pliku PDF.

