HtmlPdfPlus.Server
1.0.0
dotnet add package HtmlPdfPlus.Server --version 1.0.0
NuGet\Install-Package HtmlPdfPlus.Server -Version 1.0.0
<PackageReference Include="HtmlPdfPlus.Server" Version="1.0.0" />
<PackageVersion Include="HtmlPdfPlus.Server" Version="1.0.0" />
<PackageReference Include="HtmlPdfPlus.Server" />
paket add HtmlPdfPlus.Server --version 1.0.0
#r "nuget: HtmlPdfPlus.Server, 1.0.0"
#addin nuget:?package=HtmlPdfPlus.Server&version=1.0.0
#tool nuget:?package=HtmlPdfPlus.Server&version=1.0.0
Welcome to HtmlPdfPlus
Lightweight and scalable HTML to PDF converter in .NET.
The best tool to convert HTML to PDF in .NET with a modern engine
Table of Contents
- Project Description
- Features
- Prerequisites
- Installing
- Getting Started
- Usage
- Docker Usage
- Examples
- Documentation
- Code of Conduct
- Contributing
- Credits
- License
- FAQ
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
- 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
- .NET 8 or .NET 9 SDK
- Visual Studio 2022 or later
- Playwright (Installed and configured for your O.S)
Installing
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
Follow these steps to get started with HtmlPdfPlus:
- Install the necessary packages using NuGet.
- Configure the services in your application.
- Use the provided API to convert HTML to PDF.
Usage
It is possible to generate a PDF in two ways:
1) Using client-server mode
1.1) Via http
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
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
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
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
For more examples, please refer to the Samples directory :
- Server Only
- Console HtmlToPdfPlus OnlyAtServer V1
- Performs replacement token substitution in the HTML source before performing the conversion
- Performs writing to file after performing conversion
- Return output data with filename
- Console HtmlToPdfPlus OnlyAtServer V2
- Performs generate pdf in bytes array
- Performs writing to file
- Console HtmlToPdfPlus OnlyAtServer V1
- Client-Server
- Console HtmlToPdfPlus Client by Http
- Performs sending data to the server via http client
- Performs writing to file
- Server HtmlToPdfPlus Generic
- Performs generate pdf in bytes array
- Send data to client via http
- Console HtmlToPdfPlus Client by Http
- Client-Server Custom
- Console HtmlToPdfPlus Client Custom by Http
- Performs a generic suggestion for writing a file to a cloud like gcp/azure
- Performs sending data to the server via http client
- Server HtmlToPdfPlus Custom Save File
- Performs replacement token substitution in the HTML source before performing the conversion
- Performs a generic suggestion writing to file after performing conversion
- Send data (name of file or full path file) to client via http
- Console HtmlToPdfPlus Client Custom by Http
- Client-Server TCP
- Console HtmlToPdfPlus Client Tcp
- Performs sending data to the server via tcp client (using SuperSimpleTcp package)
- Performs receiver data from the server via tcp client
- Performs writing to file
- Server Console HtmlToPdfPlus Tcp
- Listening port on tcp server (using SuperSimpleTcp package)
- Performs generate pdf in bytes array
- Send data to client via tcp server
- Console HtmlToPdfPlus Client Tcp
Documentation
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
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
Please read Contributing for details on our code of conduct, and the process for submitting pull requests to us.
Credits
API documentation generated by
- XmlDocMarkdown, Copyright (c) 2024 Ed Ball
- See an unrefined customization to contain header and other adjustments in project XmlDocMarkdownGenerator
License
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:
- NUglify released under the BSD-Clause 2 license.
- The original Microsoft Ajax Minifier was released under the Apache 2.0 license.
FAQ
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 | Versions 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. |
-
.NETStandard 2.1
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.1)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.3)
- Microsoft.Playwright (>= 1.51.0)
- NUglify (>= 1.21.13)
- System.Text.Json (>= 8.0.5)
-
net8.0
- Microsoft.Extensions.Hosting.Abstractions (>= 8.0.1)
- Microsoft.Extensions.Logging.Abstractions (>= 8.0.3)
- Microsoft.Playwright (>= 1.51.0)
- NUglify (>= 1.21.13)
- System.Text.Json (>= 8.0.5)
-
net9.0
- Microsoft.Extensions.Hosting.Abstractions (>= 9.0.3)
- Microsoft.Extensions.Logging.Abstractions (>= 9.0.3)
- Microsoft.Playwright (>= 1.51.0)
- NUglify (>= 1.21.13)
- System.Text.Json (>= 9.0.3)
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 | 160 | 3/26/2025 | |
0.5.0-rc | 119 | 3/21/2025 | |
0.4.0-rc | 131 | 3/20/2025 | |
0.3.0-beta | 194 | 3/17/2025 | |
0.2.0-beta | 176 | 3/14/2025 | |
0.1.0-alfa | 167 | 3/12/2025 |