Przejdź do treści stopki
KORZYSTANIE Z IRONPDF

ASP.NET Core: Twórz PDF-y na bieżąco z IronPDF

Dynamicznie generuj profesjonalne dokumenty PDF w ASP.NET Core, konwertując zawartość HTML na dopracowane pliki PDF i przesyłając je bezpośrednio do przeglądarki — bez konieczności przechowywania na dysku i zarządzania plikami tymczasowymi.

Podczas tworzenia nowoczesnych aplikacji internetowych w .NET Core często pojawia się potrzeba generowania dokumentów PDF na żądanie. Faktury muszą zostać pobrane w momencie zaksięgowania płatności. Raporty zgodności muszą pojawiać się natychmiast po kliknięciu przycisku "Eksportuj" przez audytora. Certyfikaty powinny być gotowe, zanim użytkownik zdąży się zastanowić, czy coś poszło nie tak. IronPDF obsługuje wszystkie te scenariusze dzięki bibliotece PDF opartej na Chromium, która konwertuje HTML — w tym CSS, JavaScript i czcionki internetowe — na plik PDF o pikselowej dokładności bez zapisywania czegokolwiek na dysku.

Ten przewodnik zawiera wszystko, co musisz wiedzieć: instalację biblioteki, generowanie faktur z ciągów HTML, strumieniowe przesyłanie raportów z danych Entity Framework, stosowanie nagłówków stron i ustawień zabezpieczeń oraz wdrażanie najlepszych praktyk, które zapewniają wysoką wydajność aplikacji ASP.NET o dużym natężeniu ruchu.

Co oznacza tworzenie plików PDF w locie?

"On the fly" oznacza, że dokument jest tworzony w pamięci w momencie wysłania żądania HTTP i wysyłany bezpośrednio do wywołującego. Żaden plik PDF nie jest zapisywany w systemie plików, żadne zadanie w tle nie umieszcza pracy w kolejce, a żadna pamięć podręczna nie przechowuje wyniku między żądaniami.

Takie podejście ma znaczenie z kilku powodów. Po pierwsze, środowiska wdrożeń w chmurze — Azure App Service, AWS Lambda, kontenery Docker — często działają w środowiskach, w których lokalny system plików jest tymczasowy lub tylko do odczytu. Generowanie pliku PDF do folderu tymczasowego, a następnie odczytywanie go z powrotem jest w tych środowiskach zawodne. Po drugie, unikanie zapisów na dysku zmniejsza powierzchnię ataku: nie ma pliku resztkowego, który kolejne żądanie mogłoby przypadkowo dostarczyć niewłaściwemu użytkownikowi. Po trzecie, generowanie wyłącznie w pamięci jest zazwyczaj szybsze, ponieważ eliminuje dwie operacje wejścia/wyjścia (zapis i odczyt) w ścieżce krytycznej.

IronPDF ChromePdfRenderer udostępnia właściwość .BinaryData oraz właściwość .Stream w każdym wygenerowanym dokumencie. Każdy z nich można przekazać bezpośrednio do .NET Core FileResult, dzięki czemu w praktyce strumieniowanie sprowadza się do jednego wiersza kodu.

!{--01001100010010010100001001010010010000010101001001011001010111110100011101000101010101000101111101010011010101000100000101010010010101000100010101000100010111110101011101001001010100010010000101111101010000010100100100111101000100010101010100001101010100010111110101010001010010010010010100000101001100010111110100001001001100010011110100001101001011--}

Jak zainstalować IronPDF w projekcie ASP.NET Core?

Dodaj pakiet NuGet za pomocą konsoli menedżera pakietów lub interfejsu CLI platformy .NET:

Install-Package IronPdf
dotnet add package IronPdf
Install-Package IronPdf
dotnet add package IronPdf
SHELL

Po zainstalowaniu pakietu należy ustawić klucz licencyjny podczas uruchamiania aplikacji — zazwyczaj w Program.cs przed utworzeniem pierwszego renderera:

using IronPdf;

// Place license activation before any IronPDF call
License.LicenseKey = "YOUR-LICENSE-KEY";

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();

// Register ChromePdfRenderer as a singleton so the Chromium engine
// is initialised once and reused across all requests.
builder.Services.AddSingleton<ChromePdfRenderer>();

var app = builder.Build();
app.MapDefaultControllerRoute();
app.Run();
using IronPdf;

// Place license activation before any IronPDF call
License.LicenseKey = "YOUR-LICENSE-KEY";

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllersWithViews();

// Register ChromePdfRenderer as a singleton so the Chromium engine
// is initialised once and reused across all requests.
builder.Services.AddSingleton<ChromePdfRenderer>();

var app = builder.Build();
app.MapDefaultControllerRoute();
app.Run();
Imports IronPdf

' Place license activation before any IronPDF call
License.LicenseKey = "YOUR-LICENSE-KEY"

Dim builder = WebApplication.CreateBuilder(args)
builder.Services.AddControllersWithViews()

' Register ChromePdfRenderer as a singleton so the Chromium engine
' is initialised once and reused across all requests.
builder.Services.AddSingleton(Of ChromePdfRenderer)()

Dim app = builder.Build()
app.MapDefaultControllerRoute()
app.Run()
$vbLabelText   $csharpLabel

Ważne jest zarejestrowanie ChromePdfRenderer jako singletonu. Renderer uruchamia wewnętrzny podproces Chromium przy pierwszym użyciu. Jeśli tworzysz nową instancję dla każdego żądania, ponosisz ten koszt uruchomienia przy każdym wywołaniu, co powoduje opóźnienie rzędu setek milisekund przy dużym obciążeniu. Instancja singletonowa jest bezpieczna dla wątków i obsługuje równoczesne żądania renderowania bez dodatkowej konfiguracji.

Aby uzyskać szerszy przegląd opcji instalacji, w tym konfiguracji pliku NuGet.config dla prywatnych kanałów, odwiedź stronę z przeglądem instalacji.

Jak wygenerować plik PDF z fakturą na podstawie ciągu znaków HTML?

Najczęstszym przykładem zastosowania w czasie rzeczywistym jest generowanie dokumentów transakcyjnych — faktur, paragonów, potwierdzeń zamówień — gdzie treść zmienia się w zależności od żądania, ale układ pozostaje stały.

Schemat działania jest następujący: należy utworzyć ciąg HTML z interpolowanymi danymi, przekazać go do RenderHtmlAsPdf i zwrócić wynik binarny jako plik do pobrania.

using IronPdf;
using Microsoft.AspNetCore.Mvc;

public class DocumentController : Controller
{
    private readonly ChromePdfRenderer _renderer;

    public DocumentController(ChromePdfRenderer renderer)
    {
        _renderer = renderer;
    }

    [HttpGet("invoice/{orderId:int}")]
    public IActionResult GetInvoice(int orderId)
    {
        // In a real application, fetch this from your database or order service.
        var order = GetOrderData(orderId);

        string html = $"""
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="utf-8">
                <style>
                    body  {{ font-family: Arial, sans-serif; margin: 40px; color: #333; }}
                    h1   {{ color: #1a56db; }}
                    table {{ width: 100%; border-collapse: collapse; margin-top: 24px; }}
                    th, td {{ padding: 10px 14px; border: 1px solid #d1d5db; text-align: left; }}
                    th   {{ background: #f3f4f6; }}
                    tfoot td {{ font-weight: bold; }}
                </style>
            </head>
            <body>
                <h1>Invoice #{order.InvoiceNumber}</h1>
                <p>Date: {DateTime.UtcNow:yyyy-MM-dd} &nbsp;|&nbsp; Customer: {order.CustomerName}</p>
                <table>
                    <thead><tr><th>Item</th><th>Qty</th><th>Unit Price</th><th>Subtotal</th></tr></thead>
                    <tbody>
                        {string.Join("", order.Items.Select(i =>
                            $"<tr><td>{i.Name}</td><td>{i.Quantity}</td>" +
                            $"<td>${i.UnitPrice:F2}</td><td>${i.Quantity * i.UnitPrice:F2}</td></tr>"))}
                    </tbody>
                    <tfoot>
                        <tr><td colspan="3">Total</td><td>${order.Items.Sum(i => i.Quantity * i.UnitPrice):F2}</td></tr>
                    </tfoot>
                </table>
            </body>
            </html>
            """;

        var pdf = _renderer.RenderHtmlAsPdf(html);
        return File(pdf.BinaryData, "application/pdf", $"invoice-{orderId}.pdf");
    }
}
using IronPdf;
using Microsoft.AspNetCore.Mvc;

public class DocumentController : Controller
{
    private readonly ChromePdfRenderer _renderer;

    public DocumentController(ChromePdfRenderer renderer)
    {
        _renderer = renderer;
    }

    [HttpGet("invoice/{orderId:int}")]
    public IActionResult GetInvoice(int orderId)
    {
        // In a real application, fetch this from your database or order service.
        var order = GetOrderData(orderId);

        string html = $"""
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="utf-8">
                <style>
                    body  {{ font-family: Arial, sans-serif; margin: 40px; color: #333; }}
                    h1   {{ color: #1a56db; }}
                    table {{ width: 100%; border-collapse: collapse; margin-top: 24px; }}
                    th, td {{ padding: 10px 14px; border: 1px solid #d1d5db; text-align: left; }}
                    th   {{ background: #f3f4f6; }}
                    tfoot td {{ font-weight: bold; }}
                </style>
            </head>
            <body>
                <h1>Invoice #{order.InvoiceNumber}</h1>
                <p>Date: {DateTime.UtcNow:yyyy-MM-dd} &nbsp;|&nbsp; Customer: {order.CustomerName}</p>
                <table>
                    <thead><tr><th>Item</th><th>Qty</th><th>Unit Price</th><th>Subtotal</th></tr></thead>
                    <tbody>
                        {string.Join("", order.Items.Select(i =>
                            $"<tr><td>{i.Name}</td><td>{i.Quantity}</td>" +
                            $"<td>${i.UnitPrice:F2}</td><td>${i.Quantity * i.UnitPrice:F2}</td></tr>"))}
                    </tbody>
                    <tfoot>
                        <tr><td colspan="3">Total</td><td>${order.Items.Sum(i => i.Quantity * i.UnitPrice):F2}</td></tr>
                    </tfoot>
                </table>
            </body>
            </html>
            """;

        var pdf = _renderer.RenderHtmlAsPdf(html);
        return File(pdf.BinaryData, "application/pdf", $"invoice-{orderId}.pdf");
    }
}
Imports IronPdf
Imports Microsoft.AspNetCore.Mvc

Public Class DocumentController
    Inherits Controller

    Private ReadOnly _renderer As ChromePdfRenderer

    Public Sub New(renderer As ChromePdfRenderer)
        _renderer = renderer
    End Sub

    <HttpGet("invoice/{orderId:int}")>
    Public Function GetInvoice(orderId As Integer) As IActionResult
        ' In a real application, fetch this from your database or order service.
        Dim order = GetOrderData(orderId)

        Dim html As String = $"
            <!DOCTYPE html>
            <html lang=""en"">
            <head>
                <meta charset=""utf-8"">
                <style>
                    body  {{ font-family: Arial, sans-serif; margin: 40px; color: #333; }}
                    h1   {{ color: #1a56db; }}
                    table {{ width: 100%; border-collapse: collapse; margin-top: 24px; }}
                    th, td {{ padding: 10px 14px; border: 1px solid #d1d5db; text-align: left; }}
                    th   {{ background: #f3f4f6; }}
                    tfoot td {{ font-weight: bold; }}
                </style>
            </head>
            <body>
                <h1>Invoice #{order.InvoiceNumber}</h1>
                <p>Date: {DateTime.UtcNow:yyyy-MM-dd} &nbsp;|&nbsp; Customer: {order.CustomerName}</p>
                <table>
                    <thead><tr><th>Item</th><th>Qty</th><th>Unit Price</th><th>Subtotal</th></tr></thead>
                    <tbody>
                        {String.Join("", order.Items.Select(Function(i) $"<tr><td>{i.Name}</td><td>{i.Quantity}</td>" +
                            $"<td>${i.UnitPrice:F2}</td><td>${i.Quantity * i.UnitPrice:F2}</td></tr>"))}
                    </tbody>
                    <tfoot>
                        <tr><td colspan=""3"">Total</td><td>${order.Items.Sum(Function(i) i.Quantity * i.UnitPrice):F2}</td></tr>
                    </tfoot>
                </table>
            </body>
            </html>
            "

        Dim pdf = _renderer.RenderHtmlAsPdf(html)
        Return File(pdf.BinaryData, "application/pdf", $"invoice-{orderId}.pdf")
    End Function
End Class
$vbLabelText   $csharpLabel

RenderHtmlAsPdf przetwarza pełny dokument HTML — siatkę CSS, Flexbox, czcionki internetowe, a nawet wbudowane pliki SVG — korzystając z tego samego silnika Chromium, który napędza przeglądarkę Google Chrome. Zwracany PdfDocument ujawnia BinaryData (a byte[]) oraz Stream (a MemoryStream). Przekazanie BinaryData do File() wraz z "application/pdf" i nazwą pliku powoduje pobranie pliku przez przeglądarkę.

W przypadku układów wymagających idealnej wierności pikselowej należy zapoznać się z przewodnikiem renderowania HTML do PDF, który obejmuje responsywny CSS, niestandardowe czcionki i renderowanie JavaScript.

Jak wygląda wygenerowany plik PDF z fakturą?

Professional PDF invoice showing Invoice #123 dated 2025-11-13 with a styled header section, organized table containing Product A ($10.99) and Product B ($5.49), demonstrating dynamic PDF generation capabilities with custom CSS styling

Jak przesyłać plik PDF bezpośrednio do przeglądarki bez okna dialogowego pobierania?

Wyświetlanie pliku PDF w trybie inline — otwieranie go w wbudowanej przeglądarce zamiast pobierania — wymaga dwóch niewielkich zmian: ustawienia Content-Disposition na inline oraz pominięcia nazwy pliku w wywołaniu File().

[HttpPost("report/preview")]
public async Task<IActionResult> PreviewReport([FromBody] ReportRequest request)
{
    string html = BuildReportHtml(request);

    var pdfDocument = await _renderer.RenderHtmlAsPdfAsync(html);

    // "inline" tells the browser to display rather than download.
    Response.Headers["Content-Disposition"] = "inline; filename=report.pdf";

    return new FileContentResult(pdfDocument.BinaryData, "application/pdf");
}
[HttpPost("report/preview")]
public async Task<IActionResult> PreviewReport([FromBody] ReportRequest request)
{
    string html = BuildReportHtml(request);

    var pdfDocument = await _renderer.RenderHtmlAsPdfAsync(html);

    // "inline" tells the browser to display rather than download.
    Response.Headers["Content-Disposition"] = "inline; filename=report.pdf";

    return new FileContentResult(pdfDocument.BinaryData, "application/pdf");
}
Imports Microsoft.AspNetCore.Mvc

<HttpPost("report/preview")>
Public Async Function PreviewReport(<FromBody> request As ReportRequest) As Task(Of IActionResult)
    Dim html As String = BuildReportHtml(request)

    Dim pdfDocument = Await _renderer.RenderHtmlAsPdfAsync(html)

    ' "inline" tells the browser to display rather than download.
    Response.Headers("Content-Disposition") = "inline; filename=report.pdf"

    Return New FileContentResult(pdfDocument.BinaryData, "application/pdf")
End Function
$vbLabelText   $csharpLabel

W przypadku kontrolerów .NET Core zaleca się stosowanie przeciążenia async RenderHtmlAsPdfAsync, ponieważ zwalnia ono wątek z puli wątków podczas renderowania przez Chromium, zapewniając responsywność serwera przy obciążeniu współbieżnym.

Jak działa generowanie plików PDF na podstawie pamięci?

Wygenerowany raport PDF zawierający tytuł

Tablica bajtów pdfDocument.BinaryData znajduje się w całości w pamięci zarządzanej. Nie ma tu żadnych pośrednich ścieżek do plików. Nagłówek Content-Disposition określa, czy plik PDF jest wyświetlany w treści strony, czy oferowany do pobrania — jest to zachowanie przeglądarki zdefiniowane w specyfikacji HTTP. Aby uzyskać więcej informacji na temat podejścia MemoryStream, w tym przesyłania strumieniowego do usługi Azure Blob Storage, zapoznaj się z dokumentacją dotyczącą strumienia pamięci w formacie PDF.

Jak generować pliki PDF na podstawie wyników zapytań Entity Framework Core?

Większość aplikacji biznesowych pobiera dane raportów z bazy danych, zamiast tworzyć je w momencie wywołania. Poniższy wzorzec wysyła zapytanie do Entity Framework Core, tworzy tabelę HTML i zwraca plik PDF — wszystko w ramach jednej akcji kontrolera.

[HttpGet("report/monthly")]
public async Task<IActionResult> MonthlyReport(int year, int month)
{
    // Pull aggregated transaction data from EF Core.
    var rows = await _dbContext.Transactions
        .Where(t => t.Date.Year == year && t.Date.Month == month)
        .GroupBy(t => t.Category)
        .Select(g => new { Category = g.Key, Count = g.Count(), Total = g.Sum(t => t.Amount) })
        .OrderByDescending(g => g.Total)
        .ToListAsync();

    string tableRows = string.Join("", rows.Select(r =>
        $"<tr><td>{r.Category}</td><td>{r.Count}</td><td>${r.Total:F2}</td></tr>"));

    string html = $"""
        <html><body style="font-family:Arial,sans-serif;padding:32px">
        <h1>Monthly Report -- {month:D2}/{year}</h1>
        <table style="width:100%;border-collapse:collapse">
          <thead>
            <tr style="background:#e5e7eb">
              <th style="padding:8px;border:1px solid #d1d5db">Category</th>
              <th style="padding:8px;border:1px solid #d1d5db">Transactions</th>
              <th style="padding:8px;border:1px solid #d1d5db">Total</th>
            </tr>
          </thead>
          <tbody>{tableRows}</tbody>
        </table>
        </body></html>
        """;

    var pdf = _renderer.RenderHtmlAsPdf(html);
    pdf.MetaData.Title  = $"Monthly Report {month:D2}/{year}";
    pdf.MetaData.Author = "Reporting System";

    return File(pdf.BinaryData, "application/pdf", $"report-{year}-{month:D2}.pdf");
}
[HttpGet("report/monthly")]
public async Task<IActionResult> MonthlyReport(int year, int month)
{
    // Pull aggregated transaction data from EF Core.
    var rows = await _dbContext.Transactions
        .Where(t => t.Date.Year == year && t.Date.Month == month)
        .GroupBy(t => t.Category)
        .Select(g => new { Category = g.Key, Count = g.Count(), Total = g.Sum(t => t.Amount) })
        .OrderByDescending(g => g.Total)
        .ToListAsync();

    string tableRows = string.Join("", rows.Select(r =>
        $"<tr><td>{r.Category}</td><td>{r.Count}</td><td>${r.Total:F2}</td></tr>"));

    string html = $"""
        <html><body style="font-family:Arial,sans-serif;padding:32px">
        <h1>Monthly Report -- {month:D2}/{year}</h1>
        <table style="width:100%;border-collapse:collapse">
          <thead>
            <tr style="background:#e5e7eb">
              <th style="padding:8px;border:1px solid #d1d5db">Category</th>
              <th style="padding:8px;border:1px solid #d1d5db">Transactions</th>
              <th style="padding:8px;border:1px solid #d1d5db">Total</th>
            </tr>
          </thead>
          <tbody>{tableRows}</tbody>
        </table>
        </body></html>
        """;

    var pdf = _renderer.RenderHtmlAsPdf(html);
    pdf.MetaData.Title  = $"Monthly Report {month:D2}/{year}";
    pdf.MetaData.Author = "Reporting System";

    return File(pdf.BinaryData, "application/pdf", $"report-{year}-{month:D2}.pdf");
}
Imports Microsoft.AspNetCore.Mvc
Imports System.Threading.Tasks
Imports System.Linq

<HttpGet("report/monthly")>
Public Async Function MonthlyReport(year As Integer, month As Integer) As Task(Of IActionResult)
    ' Pull aggregated transaction data from EF Core.
    Dim rows = Await _dbContext.Transactions _
        .Where(Function(t) t.Date.Year = year AndAlso t.Date.Month = month) _
        .GroupBy(Function(t) t.Category) _
        .Select(Function(g) New With {Key .Category = g.Key, Key .Count = g.Count(), Key .Total = g.Sum(Function(t) t.Amount)}) _
        .OrderByDescending(Function(g) g.Total) _
        .ToListAsync()

    Dim tableRows As String = String.Join("", rows.Select(Function(r) $"<tr><td>{r.Category}</td><td>{r.Count}</td><td>${r.Total:F2}</td></tr>"))

    Dim html As String = $"
        <html><body style='font-family:Arial,sans-serif;padding:32px'>
        <h1>Monthly Report -- {month:D2}/{year}</h1>
        <table style='width:100%;border-collapse:collapse'>
          <thead>
            <tr style='background:#e5e7eb'>
              <th style='padding:8px;border:1px solid #d1d5db'>Category</th>
              <th style='padding:8px;border:1px solid #d1d5db'>Transactions</th>
              <th style='padding:8px;border:1px solid #d1d5db'>Total</th>
            </tr>
          </thead>
          <tbody>{tableRows}</tbody>
        </table>
        </body></html>
        "

    Dim pdf = _renderer.RenderHtmlAsPdf(html)
    pdf.MetaData.Title = $"Monthly Report {month:D2}/{year}"
    pdf.MetaData.Author = "Reporting System"

    Return File(pdf.BinaryData, "application/pdf", $"report-{year}-{month:D2}.pdf")
End Function
$vbLabelText   $csharpLabel

Ustawienie pdf.MetaData.Title i pdf.MetaData.Author osadza te informacje w właściwościach dokumentu PDF, co jest przydatne w systemach śledzenia zgodności i zarządzania dokumentami. W przypadku bardziej złożonych układów raportów warto rozważyć zastosowanie stylów drukowania CSS, wyraźnych podziałów stron oraz osadzonych obrazów wykresów.

Jak zastosować nagłówki, stopki i zabezpieczenia w wygenerowanych plikach PDF?

Dokumenty produkcyjne często wymagają nagłówków z tytułem dokumentu, stopek z numerami stron oraz zabezpieczeń dostępu, które zapobiegają nieautoryzowanemu drukowaniu lub kopiowaniu. ChromePdfRenderOptions firmy IronPDF spełnia wszystkie te wymagania.

[HttpPost("document/secured")]
public async Task<IActionResult> GenerateSecuredDocument([FromBody] SecuredDocRequest request)
{
    var renderOptions = new ChromePdfRenderOptions
    {
        PaperSize       = PdfPaperSize.A4,
        MarginTop       = 45,
        MarginBottom    = 45,
        MarginLeft      = 25,
        MarginRight     = 25,
        Włącz JavaScript = true,
        WaitFor         = new WaitFor { RenderDelay = 500 }
    };

    renderOptions.TextHeader = new TextHeaderFooter
    {
        CenterText       = request.DocumentTitle,
        DrawDividerLine  = true,
        FontSize         = 11
    };

    renderOptions.TextFooter = new TextHeaderFooter
    {
        LeftText  = "{date} {time}",
        RightText = "Page {page} of {total-pages}",
        FontSize  = 9
    };

    _renderer.RenderingOptions = renderOptions;

    var pdf = await _renderer.RenderHtmlAsPdfAsync(request.HtmlContent);

    if (request.RequirePassword)
    {
        pdf.SecuritySettings.OwnerPassword         = request.OwnerPassword;
        pdf.SecuritySettings.UserPassword          = request.UserPassword;
        pdf.SecuritySettings.AllowUserPrinting     = PdfPrintSecurity.NoPrint;
        pdf.SecuritySettings.AllowUserCopyPasteContent = false;
    }

    return File(pdf.BinaryData, "application/pdf", $"{request.FileName}.pdf");
}
[HttpPost("document/secured")]
public async Task<IActionResult> GenerateSecuredDocument([FromBody] SecuredDocRequest request)
{
    var renderOptions = new ChromePdfRenderOptions
    {
        PaperSize       = PdfPaperSize.A4,
        MarginTop       = 45,
        MarginBottom    = 45,
        MarginLeft      = 25,
        MarginRight     = 25,
        Włącz JavaScript = true,
        WaitFor         = new WaitFor { RenderDelay = 500 }
    };

    renderOptions.TextHeader = new TextHeaderFooter
    {
        CenterText       = request.DocumentTitle,
        DrawDividerLine  = true,
        FontSize         = 11
    };

    renderOptions.TextFooter = new TextHeaderFooter
    {
        LeftText  = "{date} {time}",
        RightText = "Page {page} of {total-pages}",
        FontSize  = 9
    };

    _renderer.RenderingOptions = renderOptions;

    var pdf = await _renderer.RenderHtmlAsPdfAsync(request.HtmlContent);

    if (request.RequirePassword)
    {
        pdf.SecuritySettings.OwnerPassword         = request.OwnerPassword;
        pdf.SecuritySettings.UserPassword          = request.UserPassword;
        pdf.SecuritySettings.AllowUserPrinting     = PdfPrintSecurity.NoPrint;
        pdf.SecuritySettings.AllowUserCopyPasteContent = false;
    }

    return File(pdf.BinaryData, "application/pdf", $"{request.FileName}.pdf");
}
Imports Microsoft.AspNetCore.Mvc

<HttpPost("document/secured")>
Public Async Function GenerateSecuredDocument(<FromBody> request As SecuredDocRequest) As Task(Of IActionResult)
    Dim renderOptions As New ChromePdfRenderOptions With {
        .PaperSize = PdfPaperSize.A4,
        .MarginTop = 45,
        .MarginBottom = 45,
        .MarginLeft = 25,
        .MarginRight = 25,
        .EnableJavaScript = True,
        .WaitFor = New WaitFor With {.RenderDelay = 500}
    }

    renderOptions.TextHeader = New TextHeaderFooter With {
        .CenterText = request.DocumentTitle,
        .DrawDividerLine = True,
        .FontSize = 11
    }

    renderOptions.TextFooter = New TextHeaderFooter With {
        .LeftText = "{date} {time}",
        .RightText = "Page {page} of {total-pages}",
        .FontSize = 9
    }

    _renderer.RenderingOptions = renderOptions

    Dim pdf = Await _renderer.RenderHtmlAsPdfAsync(request.HtmlContent)

    If request.RequirePassword Then
        pdf.SecuritySettings.OwnerPassword = request.OwnerPassword
        pdf.SecuritySettings.UserPassword = request.UserPassword
        pdf.SecuritySettings.AllowUserPrinting = PdfPrintSecurity.NoPrint
        pdf.SecuritySettings.AllowUserCopyPasteContent = False
    End If

    Return File(pdf.BinaryData, "application/pdf", $"{request.FileName}.pdf")
End Function
$vbLabelText   $csharpLabel

Ustawienie WaitFor.RenderDelay jest szczególnie przydatne, gdy kod HTML zawiera biblioteki do tworzenia wykresów, takie jak Chart.js lub ApexCharts, które kończą rysowanie asynchronicznie. Ustawienie opóźnienia na 300–500 ms gwarantuje, że Chromium uchwyci ostateczny stan renderowania. W przypadku dokumentów, które muszą spełniać standardy archiwizacji, należy połączyć powyższe podejście z zgodnością z formatem PDF/A i podpisami cyfrowymi.

Tokeny {page} i {total-pages} w tekście stopki są automatycznie rozpoznawane przez IronPDF w momencie renderowania. Dodatkowe opcje nagłówków i stopek obejmują nagłówki oparte na HTML do umieszczania logo oraz możliwości nadpisywania ustawień dla poszczególnych sekcji.

Jakie opcje renderowania są dostępne?

Poniższa tabela zawiera podsumowanie najbardziej przydatnych właściwości ChromePdfRenderOptions do generowania w locie:

Często używane właściwości ChromePdfRenderOptions
Właściwość Typ Cel
PaperSizePdfPaperSizeUstawia wymiary strony (A4, Letter, Legal, niestandardowe)
MarginTop / MarginBottomint (mm)Kontroluje odstępy w obszarze drukowania
Włącz JavaScriptboolZezwala na wykonanie kodu JS przed przechwyceniem
WaitFor.RenderDelayint (ms)Przechwytywanie opóźnień dla renderowania asynchronicznego
TextHeader / TextFooterTextHeaderFooterNagłówki i stopki stron
HtmlHeader / HtmlFooterHtmlHeaderFooterNagłówki/stopki w formacie HTML z obrazami
GrayScaleboolWynik: monochromatyczny plik PDF
FitToPaperWidthboolDostosowuje szeroką treść do strony

Jakie są najlepsze praktyki dotyczące wydajności przy generowaniu dużych ilości plików PDF?

Gdy pojedynczy serwer obsługuje setki równoczesnych żądań dotyczących plików PDF, kilka decyzji architektonicznych ma ogromny wpływ na przepustowość i opóźnienia.

Rejestracja renderera jako singleton. Jak pokazano w sekcji dotyczącej instalacji, zarejestrowanie ChromePdfRenderer jako singleton w kontenerze DI pozwala uniknąć kosztów uruchamiania nowego podprocesu Chromium dla każdego żądania. Zgodnie z wytycznymi Microsoftu dotyczącymi wydajności .NET Core, minimalizacja alokacji obiektów i ponowne wykorzystanie zasobów o wysokim koszcie to dwie najbardziej skuteczne dostępne optymalizacje.

Zawsze używaj async. RenderHtmlAsPdfAsync zwraca Task<PdfDocument> i zawiesza wątek kontrolera na czas działania Chromium. Uwalnia to pulę wątków do równoległej obsługi innych przychodzących żądań, dlatego dokumentacja async zaleca to przeciążenie dla hostów internetowych. Przeładowanie synchroniczne jest odpowiednie tylko dla narzędzi konsolowych lub usług działających w tle, gdzie blokowanie wątków jest dopuszczalne.

Przesyłaj dane bezpośrednio, pomijając tablicę pośrednią, gdy jest to możliwe. W przypadku dużych plików PDF .Stream można zapisać bezpośrednio w treści odpowiedzi bez tworzenia pełnej tablicy bajtów:

[HttpGet("document/large")]
public IActionResult StreamLargeDocument(int documentId)
{
    string html = BuildLargeDocumentHtml(documentId);
    var pdf = _renderer.RenderHtmlAsPdf(html);

    // Stream.Position is already at 0; no seek needed.
    return File(pdf.Stream, "application/pdf", $"document-{documentId}.pdf");
}
[HttpGet("document/large")]
public IActionResult StreamLargeDocument(int documentId)
{
    string html = BuildLargeDocumentHtml(documentId);
    var pdf = _renderer.RenderHtmlAsPdf(html);

    // Stream.Position is already at 0; no seek needed.
    return File(pdf.Stream, "application/pdf", $"document-{documentId}.pdf");
}
Imports Microsoft.AspNetCore.Mvc

<HttpGet("document/large")>
Public Function StreamLargeDocument(documentId As Integer) As IActionResult
    Dim html As String = BuildLargeDocumentHtml(documentId)
    Dim pdf = _renderer.RenderHtmlAsPdf(html)

    ' Stream.Position is already at 0; no seek needed.
    Return File(pdf.Stream, "application/pdf", $"document-{documentId}.pdf")
End Function
$vbLabelText   $csharpLabel

Utylizować po użyciu. PdfDocument implementuje IDisposable. Otoczenie tego wyrażenia tagiem using powoduje natychmiastowe zwolnienie bufora pamięci, co ma znaczenie podczas generowania wielu dużych plików PDF jeden po drugim:

using var pdf = _renderer.RenderHtmlAsPdf(html);
byte[] data = pdf.BinaryData;
// pdf is disposed here; data is safely copied to the local array.
return File(data, "application/pdf", "output.pdf");
using var pdf = _renderer.RenderHtmlAsPdf(html);
byte[] data = pdf.BinaryData;
// pdf is disposed here; data is safely copied to the local array.
return File(data, "application/pdf", "output.pdf");
Imports System.IO

Using pdf = _renderer.RenderHtmlAsPdf(html)
    Dim data As Byte() = pdf.BinaryData
    ' pdf is disposed here; data is safely copied to the local array.
    Return File(data, "application/pdf", "output.pdf")
End Using
$vbLabelText   $csharpLabel

W przypadku wskazówek dotyczących wdrażania w chmurze obejmujących środowiska Azure, AWS, Docker i Linux dokumentacja IronPDF zawiera uwagi dotyczące konfiguracji specyficzne dla danego środowiska. Jeśli pierwsze renderowanie po uruchomieniu jest powolne, zapoznaj się z przewodnikiem dotyczącym rozgrzewania i buforowania, aby poznać strategie wstępnej inicjalizacji renderera przed nadejściem pierwszego żądania użytkownika.

Jak dodać znak wodny do wygenerowanego pliku PDF?

Przed wysłaniem strumieniowym do każdej strony wygenerowanego dokumentu można dodać tekstowy lub graficzny znak wodny:

[HttpGet("document/draft/{id:int}")]
public IActionResult GetDraftDocument(int id)
{
    string html = BuildDocumentHtml(id);
    var pdf = _renderer.RenderHtmlAsPdf(html);

    // Stamp "DRAFT" diagonally across every page.
    pdf.ApplyWatermark(
        "<h1 style='color:rgba(200,0,0,0.25);transform:rotate(-45deg)'>DRAFT</h1>",
        rotation: 45,
        opacity: 30
    );

    return File(pdf.BinaryData, "application/pdf", $"draft-{id}.pdf");
}
[HttpGet("document/draft/{id:int}")]
public IActionResult GetDraftDocument(int id)
{
    string html = BuildDocumentHtml(id);
    var pdf = _renderer.RenderHtmlAsPdf(html);

    // Stamp "DRAFT" diagonally across every page.
    pdf.ApplyWatermark(
        "<h1 style='color:rgba(200,0,0,0.25);transform:rotate(-45deg)'>DRAFT</h1>",
        rotation: 45,
        opacity: 30
    );

    return File(pdf.BinaryData, "application/pdf", $"draft-{id}.pdf");
}
<AttributeUsage(AttributeTargets.Method, Inherited:=True, AllowMultiple:=False)>
Public Class HttpGetAttribute
    Inherits Attribute

    Public Sub New(route As String)
    End Sub
End Class

<HttpGet("document/draft/{id:int}")>
Public Function GetDraftDocument(id As Integer) As IActionResult
    Dim html As String = BuildDocumentHtml(id)
    Dim pdf = _renderer.RenderHtmlAsPdf(html)

    ' Stamp "DRAFT" diagonally across every page.
    pdf.ApplyWatermark(
        "<h1 style='color:rgba(200,0,0,0.25);transform:rotate(-45deg)'>DRAFT</h1>",
        rotation:=45,
        opacity:=30
    )

    Return File(pdf.BinaryData, "application/pdf", $"draft-{id}.pdf")
End Function
$vbLabelText   $csharpLabel

Pełne opcje konfiguracji znaków wodnych, w tym znaki wodne w postaci obrazów i kontrolę na poziomie poszczególnych stron, można znaleźć w dokumentacji dotyczącej znaków wodnych.

NuGet Zainstaluj za pomocą NuGet

PM >  Install-Package IronPdf

Sprawdź IronPDF na NuGet dla szybkiej instalacji. Z ponad 10 milionami pobrań, przekształca rozwój PDF z C#. Możesz również pobrać DLL lub instalator Windows.

Jakie są Twoje kolejne kroki?

Dynamiczne generowanie plików PDF w ASP.NET Core przebiega według spójnego schematu: należy zbudować kod HTML, wywołać RenderHtmlAsPdf lub jego asynchroniczne przeciążenie, a następnie zwrócić wynik za pomocą FileResult. IronPDF zajmuje się wszystkim pomiędzy — renderowaniem Chromium, stosowaniem CSS, wykonywaniem JavaScript — bez konieczności operacji wejścia/wyjścia na dysk na żadnym etapie.

W tym miejscu można rozważyć kilka kierunków działania w zależności od wymagań aplikacji. Jeśli Twoje pliki PDF wymagają połączenia wielu dokumentów źródłowych, przewodnik dotyczący scalania i dzielenia opisuje łączenie istniejących plików PDF ze świeżo wyrenderowanymi stronami. Jeśli chcesz, aby użytkownicy wypełniali i przesyłali formularze osadzone w pliku PDF, dokumentacja dotycząca formularzy interaktywnych pokazuje, jak tworzyć i odczytywać wartości pól. W przypadku branż podlegających regulacjom zgodność z formatem PDF/A oraz standardem dostępności PDF/UA gwarantuje, że dokumenty spełniają normy archiwizacji i dostępności.

Jeśli rozważasz wybór IronPDF spośród alternatywnych rozwiązań, porównanie iText vs IronPDF zawiera szczegółowe zestawienie techniczne obu produktów. Gdy będziesz gotowy do przejścia do środowiska produkcyjnego, kup licencję, aby odblokować wszystkie funkcje i uzyskać dostęp do priorytetowego wsparcia technicznego. Pełna dokumentacja API zawiera opisy wszystkich klas i metod omówionych w niniejszym przewodniku.

W razie pytań lub problemów podczas wdrażania pomoc służy zespół wsparcia technicznego. Jeśli chodzi o uwagi dotyczące konkretnych platform, takich jak Blazor Server lub MAUI, dedykowane przewodniki opisują różnice w konfiguracji dla każdego modelu hosta.

Często Zadawane Pytania

Jak mogę dynamicznie generować pliki PDF w ASP.NET Core?

Za pomocą IronPDF można dynamicznie generować pliki PDF w ASP.NET Core bez zapisywania ich na dysku. Umożliwia to strumieniowe przesyłanie plików PDF bezpośrednio do przeglądarek.

Jakie są zalety korzystania z IronPDF do generowania plików PDF?

IronPDF zapewnia potężny silnik renderujący, który umożliwia dynamiczne tworzenie plików PDF bezpośrednio w ramach projektów .NET Core, zapewniając natychmiastowe generowanie plików PDF bez konieczności przechowywania ich po stronie serwera.

Czy IronPDF może służyć do tworzenia faktur i raportów?

Tak, IronPDF nadaje się do tworzenia różnego rodzaju dokumentów, takich jak faktury, raporty i certyfikaty, generowanych na bieżąco w aplikacjach ASP.NET Core.

Czy podczas korzystania z IronPDF konieczne jest przechowywanie danych po stronie serwera?

Nie, IronPDF pozwala generować i przesyłać strumieniowo pliki PDF bezpośrednio do przeglądarek bez konieczności przechowywania ich na serwerze, co sprawia, że jest to rozwiązanie wydajne i szybkie.

Jakie aplikacje mogą skorzystać z generowania plików PDF w locie?

Nowoczesne aplikacje internetowe, zwłaszcza te wymagające tworzenia dokumentów w czasie rzeczywistym, takie jak systemy fakturowania i narzędzia do raportowania, mogą znacznie skorzystać z generowania plików PDF w locie, zapewnianego przez IronPDF.

Czy IronPDF obsługuje projekty .NET Core?

Tak, IronPDF jest w pełni kompatybilny z projektami .NET Core, co pozwala programistom na płynną integrację funkcji generowania plików PDF z ich aplikacjami.

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

Zespol wsparcia Iron

Jestesmy online 24 godziny, 5 dni w tygodniu.
Czat
Email
Zadzwon do mnie