IRONSOFTWAREHOME
KORZYSTANIE Z IRONPDF

Jak zbudować konwerter .NET HTML do PDF

Curtis Chau
Curtis Chau
Updated: 5 lipca 2026

Automatyzacja dostarczania dokumentów to wymóg, który pojawia się w niemalnie każdej aplikacji .NET przeznaczonej dla konkretnej branży. Po złożeniu zamówienia faktura musi dotrzeć do klienta w ciągu kilku sekund. Kiedy raport jest generowany w nocy, interesariusze oczekują, że znajdą go w swojej skrzynce odbiorczej, zanim dotrą do biura. Najprostszym i powszechnie obsługiwanym formatem dostarczania jest plik PDF wysłany jako załącznik do wiadomości e-mail. Ten przewodnik przeprowadzi cie przez pelny proces w C# - generowanie dokumentu PDF w pamieci za pomoca IronPDF, a nastepnie wysylanie go jako zalacznika do emaila przy uzyciu zarowno MailKit, jak i wbudowanej przestrzeni nazw System.Net.Mail, wszystko bez zapisania ani jednego bajtu na dysku.

Jak zainstalować wymagane pakiety?

Ten proces opiera się na dwóch pakietach: bibliotece do generowania plików PDF oraz bibliotece do wysyłania wiadomości e-mail. Zainstaluj oba za pomocą konsoli menedżera pakietów w Visual Studio lub poprzez .NET CLI.

PM > Install-Package IronPdf, MailKit

IronPDF oferuje silnik renderujący oparty na Chromium, który konwertuje HTML, CSS i JavaScript na dokumenty PDF o idealnej rozdzielczości. Działa na systemach Windows, Linux i macOS, co oznacza, że ten sam kod działa w interfejsie API .NET Core, usłudze działającej w tle lub funkcji Azure. MailKit to biblioteka zalecana przez Microsoft do wszystkich nowych projektów związanych z pocztą elektroniczną w środowisku .NET — obsługuje protokoły SMTP, IMAP, POP3, OAuth 2.0 oraz pełną konstrukcję MIME. Kod źródłowy i dokumentacja MailKit są dostępne na GitHubie.

Jak wygenerować dokument PDF w pamięci?

Klasa ChromePdfRenderer jest punktem wejsciowym do konwersji HTML na PDF. Przekaz napis HTML do RenderHtmlAsPdf, a otrzymasz obiekt PdfDocument, ktory calkowicie istnieje w pamieci. Uzyskaj dostep do surowych bajtow przez wlasciwosc BinaryData — ta tablica bajtow to dokladnie to, czego oczekuja API zalacznikow do emaila.

using IronPdf;

var renderer = new ChromePdfRenderer();

string htmlContent = """
    <h1>Order Confirmation</h1>
    <p>Thank you for your purchase.</p>
    <table>
        <tr><th>Item</th><th>Qty</th><th>Price</th></tr>
        <tr><td>Widget A</td><td>2</td><td>$19.99</td></tr>
        <tr><td>Widget B</td><td>1</td><td>$59.99</td></tr>
    </table>
    <p><strong>Order Total: $99.97</strong></p>
    """;

PdfDocument pdf = renderer.RenderHtmlAsPdf(htmlContent);

// pdf.BinaryData holds the complete PDF as a byte array
byte[] pdfBytes = pdf.BinaryData;
Console.WriteLine($"PDF generated: {pdfBytes.Length} bytes");

Metoda RenderHtmlAsPdf analizuje HTML przy uzyciu tego samego silnika Chromium, ktory napedza Google Chrome, wiec tabele, CSS Grid, Flexbox i osadzone czcionki sa renderowane dokladnie tak, jak w przegladarce. Wynikiem jest PdfDocument, ktorego wlasciwosc BinaryData zwraca cale binarium PDF bez zadnych odczytow i zapisow na dysku. Dla dokumentow, ktore zalapuja zewnetrzne obrazy lub arkusze stylow, uzyj opcjonalnego parametru BasePath, aby powiedziec IronPDF, gdzie rozwiazac wzgledne URL-e zasobow — jest to omowione szczegolowo na stronie jak-to-zrobic HTML na PDF.

Ustawianie układu strony i niestandardowych nagłówków

Przed dołączeniem pliku PDF warto skonfigurować marginesy, nagłówki lub stopki. Wszystkie opcje ukladu znajduja sie we wlasciwosci RenderingOptions:

using IronPdf;

var renderer = new ChromePdfRenderer();
renderer.RenderingOptions.MarginTop    = 15;
renderer.RenderingOptions.MarginBottom = 15;
renderer.RenderingOptions.MarginLeft   = 12;
renderer.RenderingOptions.MarginRight  = 12;

renderer.RenderingOptions.HtmlHeader = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='font-size:9pt;color:#666;text-align:right;'>Monthly Report</div>",
    DrawDividerLine = true
};

renderer.RenderingOptions.HtmlFooter = new HtmlHeaderFooter
{
    HtmlFragment = "<div style='font-size:8pt;text-align:center;'>{page} of {total-pages}</div>"
};

PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Monthly Summary</h1><p>See attached data.</p>");
byte[] pdfBytes = pdf.BinaryData;

Marginesy są w milimetrach. Tokeny {page} i {total-pages} zostaja zamienione przy renderowaniu. Strona HTML napis na PDF jak-to-zrobic zawiera pelny zestaw opcji renderowania. Przed załączeniem wygenerowanego dokumentu można również dodać do niego znaki wodne lub umieścić na nim tekst i obrazy.

Jak załączyć plik PDF do wiadomości e-mail za pomocą MailKit?

MailKit tworzy drzewo komunikatów MIME bezpośrednio, zapewniając pełną kontrolę nad typem zawartości, kodowaniem i metadanymi załączników. Pomocnicza klasa BodyBuilder upraszcza powszechny przypadek napisu lub ciala HTML z jednym lub kilkoma zalacznikami plikowymi.

using IronPdf;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;

// Step 1 -- generate the PDF in memory
var renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Monthly Report</h1><p>Generated automatically.</p>");

// Step 2 -- build the email message
var message = new MimeMessage();
message.From.Add(new MailboxAddress("Reports Service", "reports@example.com"));
message.To.Add(new MailboxAddress("Alice Smith", "alice@example.com"));
message.Subject = "Your Monthly Report is Ready";

var builder = new BodyBuilder();
builder.TextBody = "Hello Alice,\n\nPlease find your monthly report attached.\n\nRegards,\nReports Service";
builder.HtmlBody = "<p>Hello Alice,</p><p>Please find your monthly report attached.</p>";

// Add the in-memory PDF as an attachment
builder.Attachments.Add("MonthlyReport.pdf", pdf.BinaryData, new ContentType("application", "pdf"));
message.Body = builder.ToMessageBody();

// Step 3 -- send via SMTP with TLS
using var client = new SmtpClient();
await client.ConnectAsync("smtp.example.com", 587, SecureSocketOptions.StartTls);
await client.AuthenticateAsync("username", "app-password");
await client.SendAsync(message);
await client.DisconnectAsync(true);

Funkcja builder.Attachments.Add przyjmuje trzy argumenty: nazwe pliku, ktora odbiorca widzi w swoim kliencie pocztowym, surowa tablice bajtow z pdf.BinaryData oraz instancje ContentType okreslajacego typ MIME jako application/pdf. Asynchroniczne metody SMTP pozwalają na zwolnienie wątku wywołującego na czas trwania operacji sieciowej — ma to kluczowe znaczenie w kontrolerach .NET Core, które obsługują dziesiątki równoczesnych żądań.

Funkcja SecureSocketOptions.StartTls negocjuje szyfrowany kanal z serwerem SMTP na porcie 587. Dla Gmaila uzyj hasla aplikacji zamiast swojego hasla konta: wygeneruj je pod Bezpieczenstwo konta Google > Hasla aplikacji, a nastepnie przekaż je do AuthenticateAsync. W przypadku Microsoft 365, skonfiguruj uwierzytelnianie OAuth 2.0 poprzez klase SaslMechanismOAuth2 MailKit, jesli twoj najemca ma wylaczone podstawowe uwierzytelnianie.

Wysyłanie do wielu odbiorców

Aby skopiowac wiecej osob na tym samym emailu, dodaj adresy do kolekcji To, Cc, lub Bcc przed wywolaniem SendAsync:

message.To.Add(new MailboxAddress("Alice Smith",   "alice@example.com"));
message.To.Add(new MailboxAddress("Bob Jones",     "bob@example.com"));
message.Cc.Add(new MailboxAddress("Carol Manager", "carol@example.com"));

Pojedyncze wywolanie SendAsync dostarcza wiadomosc do wszystkich adresow. MailKit grupuje polecenia RCPT TO w jednej sesji SMTP, dzięki czemu wysyłanie wiadomości do wielu odbiorców nie powoduje spadku wydajności.

Jak korzystać z System.Net.Mail jako alternatywy?

Dla projektow celujacych w starsze wersje .NET lub projektow, gdzie dodanie zewnetrznego pakietu NuGet nie jest dozwolone, wbudowana przestrzen nazw System.Net.Mail zajmuje sie podstawowa dostawa SMTP. Microsoft nie zaleca już tego rozwiązania do nowych projektów, ale obsługuje ono typowe przypadki użycia bez dodatkowych zależności.

using IronPdf;
using System.Net;
using System.Net.Mail;

// Generate the PDF
var renderer = new ChromePdfRenderer();
PdfDocument pdf = renderer.RenderHtmlAsPdf("<h1>Invoice #1001</h1><p>Amount due: $350.00</p>");

// Build the mail message
using var message = new MailMessage("invoices@example.com", "customer@example.com");
message.Subject = "Invoice #1001 Attached";
message.Body    = "Your invoice is attached to this email. Please remit payment within 30 days.";
message.IsBodyHtml = false;

// Wrap the byte array in a MemoryStream for the Attachment constructor
var stream = new MemoryStream(pdf.BinaryData);
message.Attachments.Add(new Attachment(stream, "Invoice-1001.pdf", "application/pdf"));

// Send via SMTP
using var client = new SmtpClient("smtp.example.com", 587)
{
    Credentials = new NetworkCredential("username", "password"),
    EnableSsl   = true
};
await client.SendMailAsync(message);

Kluczowa roznica w porownaniu do MailKit jest taka, ze System.Net.Mail.Attachment nie akceptuje tablicy bajtow bezposrednio — musisz najpierw owinać pdf.BinaryData w MemoryStream. Zarowno MailMessage, jak i SmtpClient sa owinięte w instrukcje using, ktore usuwaja polaczenie SMTP i oproznia strumien po wyslaniu. Jesli pominiesz using na MailMessage, strumien zalacznika moze zostac usuniety, zanim wysylka skonczy sie w niektorych runtime'ach.

Wybór między MailKit a System.Net.Mail

Porównanie funkcji MailKit i System.Net.Mail
FunkcjaMailKitSystem.Net.Mail
Uwierzytelnianie OAuth 2.0TakNie
Obsługa protokołów IMAP / POP3TakNie
API oparte na asynchronicznościTakCzęściowe
Zalecenie firmy MicrosoftZalecaneStarsze wersje
Dodatkowy pakiet NuGetWymaganeNie jest wymagane
Złożona konstrukcja MIMEPełne wsparciePodstawowe

Wybierz MailKit do każdego nowego projektu, zwłaszcza jeśli serwer SMTP wymaga OAuth lub jeśli potrzebujesz IMAP do odczytu odpowiedzi. Uzyj System.Net.Mail, gdy baza kodu juz od niego zalezy, a koszt migracji nie jest uzasadniony.

Jak zastosować ten wzorzec w rzeczywistych procesach biznesowych?

Wzorzec "PDF do e-maila w pamięci" ma bezpośrednie zastosowanie w scenariuszach automatyzacji dokumentów, które napędzają większość aplikacji biznesowych.

Automatyzacja fakturowania

Moduł obsługi zamówień w sklepie internetowym generuje fakturę w formacie PDF natychmiast po zaksięgowaniu płatności. Wydarzenie OrderConfirmed wyzwala metode, ktora wywoluje RenderHtmlAsPdf z szablonowanym w Razor napisem HTML wypełnionym danymi zamowienia, a nastepnie wysyla wynik na adres email klienta. Ponieważ PDF nigdy nie dotyka systemu plików, nie ma pozostałych plików do usunięcia, brak wyścigów w współdzielonym katalogu tymczasowym i brak problemów z uprawnieniami w wdrażaniu kontenerów. Więcej informacji na temat renderowania HTML z widoków Razor można znaleźć w przewodniku po generowaniu plików PDF w ASP.NET Core.

Zaplanowana dystrybucja raportów

Usługa w tle zaplanowana za pomocą IHostedService generuje tygodniowe podsumowanie analityczne o 06:00 kazdego poniedzialku. Wysyła zapytanie do bazy danych, tworzy ciąg znaków raportu HTML, renderuje go za pomocą IronPDF i wykorzystuje MailKit do wysłania go na listę dystrybucyjną. Cały proces przebiega jako asynchroniczny przepływ pracy, więc nie zajmuje wątku z puli wątków podczas uzgadniania połączenia SMTP. W przypadku obciążeń hostowanych w Azure przewodnik po generatorze PDF Azure wyjaśnia, jak wdrożyć IronPDF w ramach usługi Azure App Service i Azure Functions.

Generowanie paragonów w ASP.NET Core

W minimalnym API lub akcji kontrolera .NET Core punkt końcowy POST odbiera ładunek transakcji, generuje paragon w formacie PDF i zwraca kod HTTP 200, jednocześnie wysyłając wiadomość e-mail. Zachowaj logike wysylania emaila w tle Task, aby odpowiedz HTTP natychmiast wrocila do klienta:

app.MapPost("/checkout", async (CheckoutRequest req, IEmailService emailService) =>
{
    var renderer = new ChromePdfRenderer();
    PdfDocument receipt = renderer.RenderHtmlAsPdf(BuildReceiptHtml(req));

    // Fire and forget -- do not await so the HTTP response is immediate
    _ = emailService.SendReceiptAsync(req.CustomerEmail, receipt.BinaryData);

    return Results.Ok(new { message = "Order confirmed." });
});

Dzięki temu czas odpowiedzi API pozostaje poniżej 100 ms, nawet gdy serwer SMTP działa wolno. emailService jest zarejestrowana jako usluga o zasiegu lub przejściowa, ktora owija SmtpClient MailKit.

Jak radzisz sobie z błędami i ponownymi próbami?

Operacje sieciowe kończą się niepowodzeniem. Serwery SMTP są chwilowo niedostępne, tokeny uwierzytelniające tracą ważność, a limity rozmiaru załączników różnią się w zależności od dostawcy. Od samego początku zadbaj o odporność ścieżki wysyłania wiadomości e-mail.

Zawiąż logikę wysyłania MailKit w try/catch i rejestruj błędy w stałej kolejce, aby można było je ponownie przetestować:

using IronPdf;
using MailKit.Net.Smtp;
using MailKit.Security;
using MimeKit;
using Microsoft.Extensions.Logging;

async Task SendPdfEmailWithRetryAsync(
    byte[] pdfBytes,
    string recipientEmail,
    string subject,
    ILogger logger,
    int maxAttempts = 3)
{
    for (int attempt = 1; attempt <= maxAttempts; attempt++)
    {
        try
        {
            var message = new MimeMessage();
            message.From.Add(new MailboxAddress("Mailer", "mailer@example.com"));
            message.To.Add(MailboxAddress.Parse(recipientEmail));
            message.Subject = subject;

            var builder = new BodyBuilder { TextBody = "Your document is attached." };
            builder.Attachments.Add("document.pdf", pdfBytes, new ContentType("application", "pdf"));
            message.Body = builder.ToMessageBody();

            using var smtpClient = new SmtpClient();
            await smtpClient.ConnectAsync("smtp.example.com", 587, SecureSocketOptions.StartTls);
            await smtpClient.AuthenticateAsync("user", "pass");
            await smtpClient.SendAsync(message);
            await smtpClient.DisconnectAsync(true);

            logger.LogInformation("Email sent to {Email} on attempt {Attempt}", recipientEmail, attempt);
            return;
        }
        catch (Exception ex) when (attempt < maxAttempts)
        {
            logger.LogWarning(ex, "Send attempt {Attempt} failed. Retrying...", attempt);
            await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, attempt)));
        }
    }
}

Wykładnicze opóźnienie — 2 sekundy po pierwszej niepowodzeniu, 4 po drugiej — zapobiega nadmiernemu obciążaniu przeciążonego serwera SMTP. W aplikacjach produkcyjnych należy zastąpić pętlę ponownych prób kolejką komunikatów (Azure Service Bus, RabbitMQ lub AWS SQS), aby awarie nie miały wpływu na ponowne uruchomienie aplikacji.

IronPDF rowniez wyrzuci PdfException, jesli zawartosc HTML nie moze zostac wyrenderowana. Wyłapuj to oddzielnie od wyjątków SMTP, aby komunikat o błędzie był konkretny:

PdfDocument pdf;
try
{
    pdf = renderer.RenderHtmlAsPdf(htmlContent);
}
catch (IronPdf.Exceptions.PdfException ex)
{
    logger.LogError(ex, "PDF rendering failed");
    throw;
}

Oddzielenie błędów renderowania od błędów dostarczania przyspiesza debugowanie. Aby uzyskać szerszy obraz obsługi błędów w zautomatyzowanych procesach przetwarzania dokumentów, 5-etapowy przewodnik po generowaniu plików PDF szczegółowo omawia wzorce walidacji.

Jak utrzymać rozmiar załącznika poniżej limitów dostawcy?

Większość komercyjnych dostawców poczty elektronicznej nakłada ograniczenia dotyczące maksymalnego rozmiaru załączników. Gmail ogranicza rozmiar pojedynczego załącznika do 25 MB; W usłudze Microsoft 365 domyślny limit dla standardowych skrzynek pocztowych wynosi 20 MB. Bogato sformatowany raport HTML z osadzonymi obrazami może nieoczekiwanie przekroczyć te limity.

Trzy techniki pomagają zachować te ograniczenia:

Kompresuj obrazy przed renderowaniem. Obrazy wbudowane powinny być w formacie skompresowanym JPEG lub WebP, a nie nieskompresowanym PNG. Logo w formacie PNG o rozdzielczości 600 dpi może zwiększyć rozmiar pliku PDF o kilka megabajtów; Plik JPEG o jakości 85% ma zazwyczaj mniej niż 200 KB przy takim samym efekcie wizualnym.

Uzyj ustawien kompresji IronPDF. Metoda PdfDocument.CompressImages zmniejsza rozdzielczosc osadzonych bitmap po renderowaniu. Wywolaj to przed odczytaniem BinaryData:

pdf.CompressImages(60); // quality 0-100
byte[] compressedPdfBytes = pdf.BinaryData;

Duże raporty należy podzielić na kilka wiadomości e-mail. Jeśli raport przekracza limit dostawcy nawet po kompresji, należy wygenerować jeden plik PDF na sekcję i wysłać każdy z nich w osobnej wiadomości e-mail. Strona jak-to-zrobic dzielic i laczyc PDF pokazuje, jak podzielic PdfDocument wedlug zakresu stron uzywajac CopyPages.

Zewnętrzne źródła dotyczące limitów rozmiaru w protokole SMTP: limity załączników w Gmailu, limity rozmiaru wiadomości w Microsoft 365.

Jakie są Twoje kolejne kroki?

Masz teraz dzialajacy szablon do generowania PDF w pamieci za pomoca IronPDF i wysylania go jako zalacznik do emaila przy uzyciu zarowno MailKit, jak i System.Net.Mail. Podejście oparte na pamięci eliminuje odczyty i zapisy na dysku, upraszcza wdrażanie w kontenerach, i skalowalne do scenariuszy o wysokiej przepustowości bez potrzeby czyszczenia tymczasowych plików.

Aby pogłębić integrację:

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ęczników.

...
Czytaj więcej

Powiązane artykuły

Key in blue circle

Uzyskaj natychmiast swój darmowy 30-dniowy Klucz Testowy.

Brak ograniczeń. 100% dostępności. Bez karty kredytowej.

bullet_checkedNie wymaga karty kredytowej ani tworzenia kontaBrak ograniczeń. 100% dostępności. Bez karty kredytowej.
  • Logo Aetna
  • Logo NASA
  • Logo GE
  • Logo Porsche
  • Logo USDA
  • Logo Qatar
Join Millions of Engineers who’ve tried IronPDF
Zarezerwuj swoje darmowe Demo na żywo
Booking Badge

Zaufane przez miliony inżynierów na całym świecie

Logotypy klientów Iron Software
Otrzymaj swoje Konsultacja Bez Zobowiązań
Wypełnij poniższy formularz lub wyślij e-mail na sales@ironsoftware.com
Twoje dane zawsze będą utrzymywane w tajemnicy.
Zaufane przez miliony inżynierów na całym świecie
Logotypy klientów Iron Software
Otrzymaj swój darmowy Klucz Próbny na 30 dni natychmiast.
Nie wymaga karty kredytowej ani tworzenia konta