Nast.Html2Pdf 1.0.0

dotnet add package Nast.Html2Pdf --version 1.0.0
                    
NuGet\Install-Package Nast.Html2Pdf -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Nast.Html2Pdf" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Nast.Html2Pdf" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="Nast.Html2Pdf" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Nast.Html2Pdf --version 1.0.0
                    
#r "nuget: Nast.Html2Pdf, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Nast.Html2Pdf@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Nast.Html2Pdf&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=Nast.Html2Pdf&version=1.0.0
                    
Install as a Cake Tool

Nast.Html2Pdf

A .NET library for converting HTML to PDF using RazorLight for template generation and PuppeteerSharp for PDF conversion.

Features

  • HTML Generation: Dynamic template support with RazorLight
  • PDF Conversion: Using PuppeteerSharp for high-quality conversion
  • Browser Pool: Performance optimization with instance reuse
  • Flexible Configuration: Customization of sizes, margins, orientation
  • Headers & Footers: Support for content in headers and footers
  • Error Handling: Complete error management with detailed information
  • External Resources: Support for fonts, images, and CSS styles
  • Dependency Injection: Complete integration with .NET DI
  • Functional Testing: Real-world document scenarios (invoices, reports, letters)
  • Logging & Diagnostics: Comprehensive performance monitoring and bottleneck detection
  • Comprehensive Documentation: Complete user guide and API reference

Installation

dotnet add package Nast.Html2Pdf

Quick Start

using Microsoft.Extensions.DependencyInjection;
using Nast.Html2Pdf.Extensions;

// Configure services
var services = new ServiceCollection();
services.AddLogging();
services.AddHtml2Pdf();

var serviceProvider = services.BuildServiceProvider();
var pdfService = serviceProvider.GetRequiredService<IHtml2PdfService>();

// Generate PDF from HTML
var html = @"
<!DOCTYPE html>
<html>
<head>
    <title>Sample Document</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .header { background: #f0f0f0; padding: 20px; }
    </style>
</head>
<body>
    <div class='header'>
        <h1>Sample Document</h1>
    </div>
    <p>This is a sample PDF document.</p>
</body>
</html>";

var result = await pdfService.GeneratePdfFromHtmlAsync(html);

if (result.Success)
{
    await File.WriteAllBytesAsync("document.pdf", result.Data);
    Console.WriteLine($"PDF generated successfully in {result.Duration.TotalMilliseconds}ms");
}

Documentation

Real-World Examples

Invoice Generation

var invoiceTemplate = @"
<html>
<body>
    <h1>Invoice #@Model.InvoiceNumber</h1>
    <p>Customer: @Model.CustomerName</p>
    <p>Date: @Model.Date.ToString("yyyy-MM-dd")</p>
    <table>
        <tr><th>Item</th><th>Price</th></tr>
        @foreach(var item in Model.Items)
        {
            <tr><td>@item.Name</td><td>$@item.Price.ToString("F2")</td></tr>
        }
    </table>
    <p><strong>Total: $@Model.Total.ToString("F2")</strong></p>
</body>
</html>";

var invoiceData = new
{
    InvoiceNumber = "INV-001",
    CustomerName = "John Doe",
    Date = DateTime.Now,
    Items = new[] { /* ... */ },
    Total = 150.00m
};

var result = await pdfService.GeneratePdfAsync(invoiceTemplate, invoiceData);

Report Generation

var reportTemplate = @"
<html>
<head>
    <script src='https://cdn.jsdelivr.net/npm/chart.js'></script>
</head>
<body>
    <h1>Monthly Report</h1>
    <div id='chart'></div>
    <script>
        // Chart.js code here
    </script>
</body>
</html>";

var result = await pdfService.GeneratePdfAsync(reportTemplate, reportData);

Performance & Diagnostics

The library includes built-in performance monitoring and diagnostics:

// Enhanced logging shows detailed timing information
[INFO] PDF Generation Started: Template | Operation ID: abc123
[INFO] Template Processing: abc123 | Type: Razor | Duration: 45ms
[INFO] HTML Generation Completed: abc123 | Duration: 67ms | HTML Length: 2048 chars
[INFO] PDF Conversion Completed: abc123 | Duration: 890ms | PDF Size: 156723 bytes
[INFO] Resource Usage: abc123 | Memory: 45 MB | Duration: 1002ms
[INFO] PDF Generation Completed: Template | Operation ID: abc123 | Duration: 1002ms

Configuration

Browser Pool

services.AddHtml2Pdf(options =>
{
    options.MinInstances = 1;        // Minimum browser instances
    options.MaxInstances = 5;        // Maximum browser instances
    options.MaxLifetimeMinutes = 60; // Max lifetime in minutes
    options.AcquireTimeoutSeconds = 30; // Timeout to acquire instance
});
});

PDF Options

var pdfOptions = new PdfOptions
{
    Format = "A4",
    PrintBackground = true,
    Margins = new PdfMargins
    {
        Top = "1cm",
        Bottom = "1cm",
        Left = "1cm",
        Right = "1cm"
    },
    Header = new PdfHeaderFooter
    {
        Template = "<div>Header Content</div>",
        Height = "1cm"
    }
};

Testing

The library includes comprehensive functional tests for real-world scenarios:

dotnet test

Run specific functional tests:

dotnet test --filter "RealWorldScenariosTests"

Requirements

  • .NET 8.0 or later
  • Windows, macOS, or Linux
  • Minimum 512MB RAM available
  • Internet connection for initial Chromium download

Contributing

  1. Fork the repository
  2. Create a feature branch
  3. Add tests for new functionality
  4. Ensure all tests pass
  5. Submit a pull request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Support


Made with ❤️ by Kevin Martinez { Console.WriteLine($"Error: {result.ErrorMessage}"); }


### Usage with Configuration

```csharp
using Nast.Html2Pdf.Helpers;

// Configure PDF options
var pdfOptions = PdfOptionsHelper.A4Standard;
pdfOptions.Landscape = true;
pdfOptions.Header = new PdfHeaderFooter
{
    Template = "<div style='text-align: center;'>My Company</div>",
    Height = "2cm"
};

// Generate PDF
var result = await html2PdfService.GeneratePdfAsync(htmlTemplate, model, pdfOptions);

Usage with Dependency Injection

using Microsoft.Extensions.DependencyInjection;
using Nast.Html2Pdf.Extensions;

// Configure services
var services = new ServiceCollection();
services.AddLogging();
services.AddHtml2Pdf(options =>
{
    options.MinInstances = 2;
    options.MaxInstances = 10;
    options.MaxLifetimeMinutes = 60;
    options.AcquireTimeoutSeconds = 30;
    options.Headless = true;
    options.AdditionalArgs = new[] { "--no-sandbox", "--disable-dev-shm-usage" };
});

var serviceProvider = services.BuildServiceProvider();
var html2PdfService = serviceProvider.GetRequiredService<IHtml2PdfService>();

Usage Examples

Generate Invoice

var invoiceTemplate = @"
    <!DOCTYPE html>
    <html>
    <head>
        <title>Invoice</title>
    </head>
    <body>
        <div class='invoice-header'>
            <h1>INVOICE</h1>
            <p>Number: @Model.Number</p>
            <p>Date: @Model.Date.ToString(""dd/MM/yyyy"")</p>
        </div>

        <div class='invoice-details'>
            <h3>Customer:</h3>
            <p>@Model.Customer.Name</p>
            <p>@Model.Customer.Address</p>
        </div>

        <table class='invoice-table'>
            <thead>
                <tr>
                    <th>Description</th>
                    <th>Quantity</th>
                    <th>Price</th>
                    <th>Total</th>
                </tr>
            </thead>
            <tbody>
                @foreach(var item in Model.Items)
                {
                    <tr>
                        <td>@item.Description</td>
                        <td>@item.Quantity</td>
                        <td>@item.Price.ToString(""C"")</td>
                        <td>@item.Total.ToString(""C"")</td>
                    </tr>
                }
            </tbody>
        </table>

        <div class='invoice-total'>
            <h3>Total: @Model.Total.ToString(""C"")</h3>
        </div>
    </body>
    </html>";

var invoice = new
{
    Number = "INV-001",
    Date = DateTime.Now,
    Customer = new { Name = "John Doe", Address = "123 Main St, City" },
    Items = new[]
    {
        new { Description = "Product 1", Quantity = 2, Price = 100.00m, Total = 200.00m },
        new { Description = "Product 2", Quantity = 1, Price = 150.00m, Total = 150.00m }
    },
    Total = 350.00m
};

var result = await html2PdfService.GeneratePdfAsync(
    invoiceTemplate,
    invoice,
    PdfOptionsHelper.Invoice,
    HtmlOptionsHelper.Invoice
);

Generate Report

var reportTemplate = @"
    <!DOCTYPE html>
    <html>
    <head>
        <title>Sales Report</title>
    </head>
    <body>
        <div class='report-header'>
            <h1>SALES REPORT</h1>
            <p>Period: @Model.StartDate.ToString(""dd/MM/yyyy"") - @Model.EndDate.ToString(""dd/MM/yyyy"")</p>
        </div>

        <div class='report-summary'>
            <h3>Summary</h3>
            <p>Total Sales: @Model.TotalSales.ToString(""C"")</p>
            <p>Number of Transactions: @Model.TransactionCount</p>
        </div>

        <div class='report-section'>
            <h3>Sales Detail</h3>
            <table class='report-table'>
                <thead>
                    <tr>
                        <th>Date</th>
                        <th>Customer</th>
                        <th>Product</th>
                        <th>Quantity</th>
                        <th>Amount</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach(var sale in Model.Sales)
                    {
                        <tr>
                            <td>@sale.Date.ToString(""dd/MM/yyyy"")</td>
                            <td>@sale.Customer</td>
                            <td>@sale.Product</td>
                            <td>@sale.Quantity</td>
                            <td>@sale.Amount.ToString(""C"")</td>
                        </tr>
                    }
                </tbody>
            </table>
        </div>
    </body>
    </html>";

var report = new
{
    StartDate = DateTime.Now.AddDays(-30),
    EndDate = DateTime.Now,
    TotalSales = 5000.00m,
    TransactionCount = 25,
    Sales = new[]
    {
        new { Date = DateTime.Now.AddDays(-5), Customer = "John Doe", Product = "Product A", Quantity = 2, Amount = 200.00m },
        new { Date = DateTime.Now.AddDays(-3), Customer = "Jane Smith", Product = "Product B", Quantity = 1, Amount = 150.00m },
        // more data...
    }
};

var result = await html2PdfService.GeneratePdfAsync(
    reportTemplate,
    report,
    PdfOptionsHelper.Report,
    HtmlOptionsHelper.Report
);

Predefined Configurations

PDF Options

// Available configurations
var a4Standard = PdfOptionsHelper.A4Standard;
var a4Landscape = PdfOptionsHelper.A4Landscape;
var letterStandard = PdfOptionsHelper.LetterStandard;
var noMargins = PdfOptionsHelper.NoMargins;
var invoice = PdfOptionsHelper.Invoice;
var report = PdfOptionsHelper.Report;

// Custom configuration
var custom = PdfOptionsHelper.WithHeaderAndFooter(
    headerTemplate: "<div>My Header</div>",
    footerTemplate: "<div>My Footer</div>"
);

// Custom size
var customSize = PdfOptionsHelper.WithCustomSize(8.5f, 11f); // Letter size

HTML Options

// Available configurations
var standard = HtmlOptionsHelper.Standard;
var invoice = HtmlOptionsHelper.Invoice;
var report = HtmlOptionsHelper.Report;

// Custom CSS
var withCustomCss = HtmlOptionsHelper.WithCustomCss(@"
    body { font-family: 'Times New Roman', serif; }
    .highlight { background-color: yellow; }
");

Extension Methods

// Save directly to file
await html2PdfService.GeneratePdfToFileAsync(template, model, "output.pdf");

// Get as Stream
var stream = await html2PdfService.GeneratePdfToStreamAsync(template, model);

// From template file
await html2PdfService.GeneratePdfFromFileToFileAsync("template.html", model, "output.pdf");

// From URL
await html2PdfService.GeneratePdfFromUrlToFileAsync("https://example.com", "output.pdf");

Error Handling

var result = await html2PdfService.GeneratePdfAsync(template, model);

if (result.Success)
{
    Console.WriteLine($"PDF generated successfully in {result.Duration.TotalMilliseconds}ms");
    Console.WriteLine($"Size: {result.Size} bytes");

    // Use result.Data
    File.WriteAllBytes("output.pdf", result.Data);
}
else
{
    Console.WriteLine($"Error: {result.ErrorMessage}");

    if (result.Exception != null)
    {
        Console.WriteLine($"Exception: {result.Exception.Message}");
    }
}

Advanced Configuration

Browser Pool Settings

services.AddHtml2Pdf(options =>
{
    options.MinInstances = 2;          // Minimum 2 instances
    options.MaxInstances = 10;         // Maximum 10 instances
    options.MaxLifetimeMinutes = 60;   // 1 hour lifetime
    options.AcquireTimeoutSeconds = 30; // 30 seconds timeout
    options.Headless = true;           // Run without GUI
    options.AdditionalArgs = new[] { "--no-sandbox", "--disable-dev-shm-usage" };
});

Lifetime Configuration

services.AddHtml2PdfWithLifetime(
    configureBrowserPool: options => { /* configuration */ },
    browserPoolLifetime: ServiceLifetime.Singleton,
    serviceLifetime: ServiceLifetime.Scoped
);

Advanced Templates

With External Resources

var templateWithResources = @"
    <!DOCTYPE html>
    <html>
    <head>
        <style>
            @import url('https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap');
            body { font-family: 'Roboto', sans-serif; }
        </style>
    </head>
    <body>
        <img src='https://via.placeholder.com/300x200' alt='Image' />
        <h1>Title with external font</h1>
    </body>
    </html>";

var options = new PdfOptions
{
    WaitForImages = true,  // Wait for images to load
    TimeoutMs = 30000     // 30 seconds timeout
};

With Page Breaks

var templateWithPageBreaks = @"
    <style>
        .page-break { page-break-after: always; }
    </style>

    <div>
        <h1>Page 1</h1>
        <p>Content of the first page</p>
    </div>

    <div class='page-break'></div>

    <div>
        <h1>Page 2</h1>
        <p>Content of the second page</p>
    </div>";

License

This project is licensed under the MIT License. See the LICENSE file for more details.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 222 7/16/2025