HtmlPdfPlus.Server 1.0.0

dotnet add package HtmlPdfPlus.Server --version 1.0.0
                    
NuGet\Install-Package HtmlPdfPlus.Server -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="HtmlPdfPlus.Server" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="HtmlPdfPlus.Server" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="HtmlPdfPlus.Server" />
                    
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 HtmlPdfPlus.Server --version 1.0.0
                    
#r "nuget: HtmlPdfPlus.Server, 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.
#addin nuget:?package=HtmlPdfPlus.Server&version=1.0.0
                    
Install HtmlPdfPlus.Server as a Cake Addin
#tool nuget:?package=HtmlPdfPlus.Server&version=1.0.0
                    
Install HtmlPdfPlus.Server as a Cake Tool

HtmlPdfPLus Logo Welcome to HtmlPdfPlus

Lightweight and scalable HTML to PDF converter in .NET.

GitHub license

The best tool to convert HTML to PDF in .NET with a modern engine

Build Publish

  • Client : NuGet Client NuGet Client
  • Server : NuGet Server NuGet Server

Table of Contents

Project Description

HtmlPdfPlus is a modern and lightweight library for .Net9, .Net8 and NetStandard2.1 that allows you to convert HTML or RAZOR pages to PDF with high fidelity.

It is a scalable and flexible solution that can be used in client-server mode or only server. It supports CSS and JavaScript, and it is easy to integrate with your application.

You can customize the PDF settings, such as page size and margins, and add headers and footers to your PDF files. HtmlPdfPlus is a powerful tool that can help you generate PDF files from HTML or RAZOR pages with ease.

This library was built using the Playwright (engine to automate Chromium, Firefox, and WebKit with a single API). Playwright is built to enable cross-browser web automation that is evergreen, capable, reliable, and fast.

The current version (V.1.51.0) of Playwright supports only the Chromium browser for the PDF API.

Features

Top

  • Convert HTML or RAZOR page to PDF with high fidelity
  • Support for CSS and JavaScript
  • Asynchronous API
  • Customizable PDF settings (e.g., page size, margins)
  • Support for headers and footers
  • Lightweight and easy to integrate
  • Flexible and scalable (Client-Server mode or only Server)
  • Support HTML5 and CSS3
  • Communicate with the server using REST API (with compressed request) or user custom protocol
  • Minify HTML and CSS
  • Client-side HTML parser with custom error action (optional)
  • Compress send data over network
  • Compress result PDF using GZip over network (Only type bytes array output)
  • Extension on server side to customize the conversion process (before and after conversion)
    • BeforePDF : Normalize HTML, Replace tokens, etc
    • AfterPDF : Save file, Send to cloud, etc
  • Disable features to improve/ balance performance (minify, compress and log)

What's new in the latest version

  • v1.0.0 (latest version)

    • Updated Playwright to version 1.51.0
    • Adjusted package reference for target framework
    • Updated documentation
    • GA version (jump to version 1.0.0)
  • v0.5.0-rc

    • Simplified sending data to the server via http client (now aceept byte[] instead of stream)
    • Removed ReadToBytesAsync stream extension method
    • Exposing the RequestHtmlPdf<T> class for scenarios of handling sending parameters
    • Updated documentation
    • Preparation for GA version
  • v0.4.0-rc

    • Relaxation of Package Reference for .net8 to .net9
    • Renamed the 'Source' command to 'Scope'
    • Renamed the 'Request' command to 'ScopeRequest'
    • Changed parameter in funcion SubmitHtmlToPdf to byte[] instead of string
    • Changed parameter for command Run to byte[] instead of string
    • Changed parameter for command ScopeRequest to byte[] instead of string
    • Removed DecompressBytes() method to class HtmlPdfResult
    • Added DecompressOutputData() method to class HtmlPdfResult for custom scenarios
    • Improvements in the compression/decompression process to use asynchronous methods
    • Small code reviews
  • v0.3.0-beta

    • Added FromUrl(Uri value) command to client-side mode
    • Fixed bug in server mode for multi thread safe when there is parameter customization and/or no client mode sending.
      • Moved the BeforePDF(Func<string, TIn?, CancellationToken, Task<string>> inputParam) command to the execution context.
      • Moved the AfterPDF(Func<byte[]?, TIn?, CancellationToken, Task<TOut>> outputParam) command to the execution context.
      • Added command Source(TIn? inputparam = default) to transfer input parameter for server execution context and custom actions and html source.
      • Added Request(string request Client) command to pass the request client data to the server execution context for custom actions and HTML source.
      • Simplified execution commands for server side with execution context with fluid interface comands :
        • Removed static class RequestHtmlPdf
        • Added command FromHtml(string html, int converttimeout = 30000, bool minify = true)
        • Added command FromUrl(Uri value, int converttimeout = 30000)
        • Added command FromRazor<T>(string template, T model, int converttimeout = 30000, bool minify = true)
  • v0.2.0-beta

    • Initial version

Prerequisites

Top

  • .NET 8 or .NET 9 SDK
  • Visual Studio 2022 or later
  • Playwright (Installed and configured for your O.S)

Installing

Top

Installation Steps for Playwright (Windows)

dotnet tool update --global PowerShell
dotnet tool install --global Microsoft.Playwright.CLI
playwright.exe install --with-deps

Note: Make sure that the path to the executable is mapped to: C:\Users\[login]\.dotnet\tools.

If it is not, run it directly via the path C:\Users\[login]\.dotnet\tools\playwright.exe install --with-deps

Installation Steps for HtmlPdfPlus

Client library can be installed via NuGet or line command.

Install-Package HtmlPdfPlus.Client [-pre]
dotnet add package HtmlPdfPlus.Client [--prerelease]

Server library can be installed via NuGet or line command.

Install-Package HtmlPdfPlus.Server [-pre]
dotnet add package HtmlPdfPlus.Server [--prerelease]

Note: [-pre]/[--prerelease] usage for pre-release versions

Getting Started

Top

Follow these steps to get started with HtmlPdfPlus:

  1. Install the necessary packages using NuGet.
  2. Configure the services in your application.
  3. Use the provided API to convert HTML to PDF.

Usage

Top

It is possible to generate a PDF in two ways:

1) Using client-server mode

1.1) Via http

HtmlPdfPLus Logo

basic usage client side
using HtmlPdfPlus;

...
Host.CreateDefaultBuilder(args).ConfigureServices((hostContext, services) =>
{ 
   services.AddHttpClient("HtmlPdfServer", httpClient =>
   {
      httpClient.BaseAddress = new Uri("https://localhost:7212/GeneratePdf");
   });
});
...

//client http to endpoint    
var clienthttp = HostApp!.Services
	.GetRequiredService<IHttpClientFactory>()
	.CreateClient("HtmlPdfServer");

//create client instance and send to HtmlPdfPlus server endpoint    
var pdfresult = await HtmlPdfClient
    .Create("HtmlPdfPlusClient")
    .PageConfig((cfg) =>
    {
       cfg.Margins(10)
          .Footer("'<span style=\"text-align: center;width: 100%;font-size: 10px\"> <span class=\"pageNumber\"></span> of <span class=\"totalPages\"></span></span>")
          .Header("'<span style=\"text-align: center;width: 100%;font-size: 10px\" class=\"title\"></span>")
          .Orientation(PageOrientation.Landscape)
          .DisplayHeaderFooter(true);
     })
     .Logger(HostApp.Services.GetService<ILogger<Program>>())
     .FromHtml(HtmlSample())
     .Timeout(5000)
     .Run(clienthttp, applifetime.ApplicationStopping);

//performs writing to file after performing conversion
if (pdfresult.IsSuccess)
{
    await File.WriteAllBytesAsync("html2pdfsample.pdf", pdfresult.OutputData!);
}
else
{
    //show error via pdfresult.Error
}
basic usage Server side
using HtmlPdfPlus;

...
var builder = WebApplication.CreateBuilder(args);  
builder.Services.AddHtmlPdfService((cfg) =>
{
    cfg.Logger(LogLevel.Debug, "MyPDFServer");
});
...

app.MapPost("/GeneratePdf", async ([FromServices] IHtmlPdfServer<object, byte[]> PDFserver, [FromBody] byte[] requestclienthtmltopdf, CancellationToken token) =>
{
    return await PDFserver
        .Run(requestclienthtmltopdf, token);
}).Produces<HtmlPdfResult<byte[]>>(200);

1.2) Via any process

HtmlPdfPLus Logo

basic usage client side
using HtmlPdfPlus;

// Generic suggestion for writing a file to a cloud like gcp/azure
// Suggested return would be the full path "repo/filename"
var paramTosave = new DataSavePDF("Filename.pdf","MyRepo","MyConnectionstring");

var pdfresult = await HtmlPdfClient.Create("HtmlPdfPlusClient")
      .PageConfig((cfg) =>
      {
         cfg.Margins(10);
      })
      .Logger(HostApp.Services.GetService<ILogger<Program>>())
      .FromRazor(TemplateRazor(), order1)
      .Timeout(50000)
      .Run<DataSavePDF,string>(SendToServer,paramTosave, applifetime.ApplicationStopping);

//Shwo result
if (pdfresult.IsSuccess)
{
   Console.WriteLine($"File PDF generate at {pdfresult.OutputData}");
}
else
{
    Console.WriteLine($"HtmlPdfClient error: {pdfresult.Error!}");
}

private static async Task<HtmlPdfResult<string>> SendToServer(byte[] requestdata, CancellationToken token)
{
   //send requestdata to server and return result
}

basic usage Server side
using HtmlPdfPlus;

...
var builder = WebApplication.CreateBuilder(args);  
builder.Services.AddHtmlPdfService<DataSavePDF,string>((cfg) =>
{
    cfg.Logger(LogLevel.Debug, "MyPDFServer");
});
...
var PDFserver = HostApp.Services.GetHtmlPdfService();

var result = await PDFserver
        .ScopeRequest(data)
        .BeforePDF( (html,inputparam, _) =>
        {
            if (inputparam is null)
            {
                return Task.FromResult(html);
            }
            //performs replacement token substitution in the HTML source before performing the conversion
            var aux = html.Replace("[{FileName}]", inputparam.Filename);
            return Task.FromResult(aux);
        })
        .AfterPDF( (pdfbyte, inputparam, token) =>
        {
            if (inputparam is null)
            {
                return Task.FromResult(string.Empty);
            }
            //TODO : performs writing to file  after performing conversion
            return Task.FromResult(inputparam.Filename);
        })
        .Run(token);

//send result to client

2) Using ony-server

HtmlPdfPLus Logo

basic usage
using HtmlPdfPlus;

...
Host.CreateDefaultBuilder(args)
    .ConfigureServices((hostContext, services) =>
    {
        services.AddHtmlPdfService((cfg) =>
        {
               .Logger(LogLevel.Debug, "MyPDFServer")
               .DefaultConfig((page) =>
               {
                   page.DisplayHeaderFooter(true)
                       .Margins(10, 10, 10, 10);
               });
        });
    });
...

//instance of Html to Pdf Engine and Warmup HtmlPdfServerPlus
var PDFserver = HostApp!.Services.GetHtmlPdfService();

//Performs conversion and custom operations on the server
var pdfresult = await PDFserver
       .ScopeData()
       .FromHtml(HtmlSample(),5000)
       .Run(applifetime.ApplicationStopping);

//performs writing to file after performing conversion
if (pdfresult.IsSuccess)
{
    await File.WriteAllBytesAsync( "html2pdf.pdf", pdfresult.OutputData!);
}
else
{
    //show error via pdfresult.Error
}

Docker Usage

Top

The use of Playwright works very well for local testing on Windows machines following the standard installation instructions.

For containerization scenarios, image sizes are a challenge that deserves more dedicated attention.

This project suggests a containerization example that reduces the final image size by approximately 70% !.

To achieve this reduction, the biggest challenge was controlling the necessary dependencies and keeping only the minimum for execution in a headless shell.

Basically, what we did was:

  • Use the base image from mcr.microsoft.com/dotnet/aspnet:9.0
  • Use the image from cr.microsoft.com/playwright/dotnet:v1.51.0 for build
    • Removing unnecessary browser and driver installations
    • For .NET 9, we removed the default installation (.NET 8)
      • We installed the .NET 9 SDK version for the build phase
  • Copy the required folder (pre-installed) to run Playwright
  • Install Google Chrome Stable , fonts and install the necessary libs to make the browser work.
  • Set environment variable for Playwright
  • Enable running the service as a non-root user

I believe this work can still be improved! For reference on this approach, see the DockFile.

Examples

Top

For more examples, please refer to the Samples directory :

Documentation

Top

The library is well documented and has a main namespace HtmlPdfPlus for client and server, and all methods use fluent interface.

The documentation is available in the Docs directory.

Code of Conduct

Top

This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community. For more information see the Code of Conduct.

Contributing

Top

Please read Contributing for details on our code of conduct, and the process for submitting pull requests to us.

Credits

Top

API documentation generated by

License

Top

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

Disclaimer : HtmlPdfPlus <u>includes PackageReference</u> from other software released under other licences:

FAQ

Top

Q: What browsers are supported for PDF generation?

A: Currently, only the Chromium browser is supported for the PDF API.

Q: What init args for speed and reduce resource usage ?

A: Currently, HtmlPdfPlus.Server starts with "--run-all-compositor-stages-before-draw --disable-dev-shm-usage -disable-setuid-sandbox --no-sandbox" when no argument value is passed.

Q: Can I customize the PDF settings?

A: Yes, you can customize settings such as page size, margins, headers, and footers.

Q: Is there support for asynchronous operations?

A: Yes, the API supports asynchronous operations.

Q: How can I contribute to the project?

A: Please refer to the Contributing section for details on how to contribute.

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  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 is compatible.  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. 
.NET Core netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.1 is compatible. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos 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.