The HTML to PDF Converter turns web pages and HTML strings into PDF documents. It renders the HTML with a Chromium engine that ships inside the NuGet package, so HTML5, CSS3, JavaScript, web fonts and SVG come out as in the Chrome browser, and there is no browser to install on the server. The same component converts HTML to images with the HtmlToImageConverter class.
A conversion takes three steps: create an HtmlToPdfConverter object, optionally set its options, and call one of its methods with a URL or an HTML string. The result is a PDF document in memory or in a file. A new converter already produces an A4 document with the page laid out as in a desktop browser, so the options are needed only to change that result or to add features to the document.
This topic describes the packages, the conversion methods, the page layout and the features of the converter, with links to the topics that describe each of them in detail. It ends with the code of the Getting Started demo.
The component is distributed as a NuGet package for each platform. Each package contains the same .NET Standard 2.0 library, used from .NET 6 to .NET 10 and from .NET Framework 4.6.2 to 4.8.1, and the native rendering engine for its platform.
Platform | HTML to PDF package |
|---|---|
Windows x64 | |
Linux x64 |
The Winnovative.Pdf.Next.Windows and Winnovative.Pdf.Next.Linux metapackages reference the HTML to PDF package of their platform together with all the other components of the library, and Winnovative.Pdf.Next.Windows.Arm64, Winnovative.Pdf.Next.Linux.Arm64 and Winnovative.Pdf.Next.MacOS do the same for Windows and Linux on ARM64 and for macOS on Apple Silicon. The Winnovative.Pdf.Next.HtmlToPdf and Winnovative.Pdf.Next metapackages reference both the Windows x64 and the Linux x64 packages, for applications built once and deployed on either platform. Installing and running the packages is described in Getting Started on Windows and Getting Started on Linux.
The HtmlToPdfConverter class converts a URL, which can also be a local file, or an HTML string. An HTML string is converted with a base URL, used to resolve the relative URLs of the images, style sheets and scripts it references. The PDF document is returned in a memory buffer or saved to a file:
Source | PDF in memory | PDF saved to a file |
|---|---|---|
URL or local file | ||
HTML string |
Each method has an asynchronous variant with the Async suffix, following the Task-based Asynchronous Pattern, with an optional System.ThreadingCancellationToken to cancel the conversion: ConvertUrlAsync(String, CancellationToken), ConvertHtmlAsync(String, String, CancellationToken), ConvertUrlToFileAsync(String, String, CancellationToken) and ConvertHtmlToFileAsync(String, String, String, CancellationToken). Converters can run in parallel, one per conversion, as shown in Convert Multiple HTML Pages to PDF in Parallel; how the rendering engine processes are started and reused is described in HTML to PDF Rendering Modes and the Persistent Rendering Engine.
The size of the PDF pages, the width at which the HTML is laid out and the scale at which it is drawn are set together by a layout method of the converter. A new converter uses FitBrowserWindowToPage(PdfPageSize, PdfPageOrientation, Int32) with an A4 page: the page is laid out as in a 1024 pixel browser window and scaled to the page width. HTML templates designed for the paper size use LayoutAtPageWidth(PdfPageSize, PdfPageOrientation, Boolean, String), and other methods cover the output of Chrome, receipts and pages as wide as the browser window. The methods and the settings for the usual cases are described in HTML to PDF Page Setup and Scaling, and all the options of the converter in HTML to PDF Converter Options.
Beyond the conversion itself, the converter adds structure, interactivity and security to the generated document, and controls how the page is loaded before it is converted.
Page structure
HTML headers and footers with page numbers, also in browser mode and on a PDF from multiple HTML pages
HTML stamps on the generated pages
Page breaks and unbroken elements controlled from CSS
Table headers and footers repeated on each page
Several HTML pages merged into one PDF document
Navigation and content
Bookmarks, a table of contents and internal links created from the HTML
Selected elements converted or excluded, and the positions of HTML elements in the PDF
SVG and web fonts rendered as vector graphics and embedded fonts
Interactivity, standards and security
PDF forms created from HTML forms
PDF/UA and PDF/A documents for accessibility and archiving
Loading the page
HTTP headers, cookies, GET and POST requests and authentication
The current page of a web application and a page in the same session
The moment of the conversion, for pages that load content asynchronously, and the screen or print media type
using System;
using System.ComponentModel.DataAnnotations;
using Microsoft.AspNetCore.Mvc;
using Winnovative_Next_AspNetDemo.Models;
using Winnovative_Next_AspNetDemo.Models.HTML_to_PDF;
// Use Winnovative Namespace
using Winnovative.Pdf.Next;
namespace Winnovative_Next_AspNetDemo.Controllers.HTML_to_PDF
{
public class HTML_to_PDF_Getting_StartedController : Controller
{
// GET: Getting_Started
public ActionResult Index()
{
var model = new HTML_to_PDF_Getting_Started_ViewModel();
return View(model);
}
[HttpPost]
public ActionResult ConvertHtmlToPdf(HTML_to_PDF_Getting_Started_ViewModel model)
{
if (!ModelState.IsValid)
{
var errorMessage = ModelStateHelper.GetModelErrors(ModelState);
throw new ValidationException(errorMessage);
}
// Set the license key received after purchase to use the library in licensed mode; leave it commented for demo mode
// Licensing.LicenseKey = "your-license-key";
// Create a HTML to PDF converter object with default settings
HtmlToPdfConverter htmlToPdfConverter = new HtmlToPdfConverter();
// Set the initial HTML viewer height in pixels
if (model.HtmlViewerHeight.HasValue)
htmlToPdfConverter.HtmlViewerHeight = model.HtmlViewerHeight.Value;
// Optionally load the lazy images
htmlToPdfConverter.LoadLazyImages = model.LoadLazyImages;
// Set the lazy images load mode
htmlToPdfConverter.LazyImagesLoadMode = model.LazyImagesLoadMode == "Browser" ?
LazyImagesLoadMode.Browser : LazyImagesLoadMode.Custom;
// Set the PDF page margins in points. The default is 0
htmlToPdfConverter.PdfDocumentOptions.LeftMargin = model.LeftMargin;
htmlToPdfConverter.PdfDocumentOptions.RightMargin = model.RightMargin;
htmlToPdfConverter.PdfDocumentOptions.TopMargin = model.TopMargin;
htmlToPdfConverter.PdfDocumentOptions.BottomMargin = model.BottomMargin;
// Set the media type used in @media rules when rendering HTML to PDF
htmlToPdfConverter.MediaType = model.MediaType == "Print" ? "print" : "screen";
// Set the page layout: how the width at which the HTML is laid out relates to the PDF page width
PdfPageSize pageSize = SelectedPdfPageSize(model.PdfPageSize);
PdfPageOrientation pageOrientation = SelectedPdfPageOrientation(model.PdfPageOrientation);
switch (model.PageLayout)
{
case "FitBrowserWindowToPage":
// Fixed page size: the HTML is laid out as in a browser window of the given width and the result
// is scaled to the content width of the page, so a responsive site keeps its desktop layout.
// This is the default layout of the converter, with an A4 page and a 1024 pixel window
htmlToPdfConverter.FitBrowserWindowToPage(pageSize, pageOrientation, model.HtmlViewerWidth);
break;
case "LayoutAtPageWidth":
// Fixed page size: the HTML is laid out at the content width of the page, one CSS pixel
// being 0.75 points. For HTML templates designed for the paper size, usually with the print media type
htmlToPdfConverter.LayoutAtPageWidth(pageSize, pageOrientation, mediaType: htmlToPdfConverter.MediaType);
break;
default:
// The PDF page width follows the browser window width and the HTML is drawn 1:1;
// the page height comes from the page size and the orientation
htmlToPdfConverter.PageWidthFromBrowserWindow(model.HtmlViewerWidth, singlePage: model.SinglePage);
htmlToPdfConverter.HtmlViewerZoom = model.HtmlViewerZoom;
htmlToPdfConverter.PdfDocumentOptions.PdfPageSize = pageSize;
htmlToPdfConverter.PdfDocumentOptions.PdfPageOrientation = pageOrientation;
break;
}
// A single page as tall as the content, with the page width of the layout. The page is at least as tall
// as the browser window, so the window height is set to 1 pixel for the page to end with the content
if (model.SinglePage)
{
htmlToPdfConverter.PdfDocumentOptions.AutoResizePdfPageHeight = true;
htmlToPdfConverter.HtmlViewerHeight = 1;
}
// Sets the PDF standard for the generated document
// Leave as None to generate a plain PDF without an accessibility structure tree or archival metadata
htmlToPdfConverter.PdfDocumentOptions.PdfStandard = model.PdfStandard;
// Set the maximum time, in seconds, to wait for the HTML page to load
// The default value is 120 seconds
htmlToPdfConverter.NavigationTimeout = model.NavigationTimeout;
// Set an additional delay, in seconds, to wait for asynchronous content after the initial load
// The default value is 0
if (model.ConversionDelay.HasValue)
htmlToPdfConverter.ConversionDelay = model.ConversionDelay.Value;
// The buffer to receive the generated PDF document
byte[] outPdfBuffer = null;
if (model.HtmlPageSource == "Url")
{
string url = model.Url;
// Convert the HTML page given by an URL to a PDF document in a memory buffer
outPdfBuffer = htmlToPdfConverter.ConvertUrl(url);
}
else
{
string htmlString = model.HtmlString;
string baseUrl = model.BaseUrl;
// Convert a HTML string with a base URL to a PDF document in a memory buffer
outPdfBuffer = htmlToPdfConverter.ConvertHtml(htmlString, baseUrl);
}
// Send the PDF file to browser
FileResult fileResult = new FileContentResult(outPdfBuffer, "application/pdf");
if (!model.OpenInline)
{
// send as attachment
fileResult.FileDownloadName = "HTML_to_PDF_Getting_Started.pdf";
}
return fileResult;
}
private PdfPageSize SelectedPdfPageSize(string selectedValue)
{
switch (selectedValue)
{
case "A0":
return PdfPageSize.A0;
case "A1":
return PdfPageSize.A1;
case "A10":
return PdfPageSize.A10;
case "A2":
return PdfPageSize.A2;
case "A3":
return PdfPageSize.A3;
case "A4":
return PdfPageSize.A4;
case "A5":
return PdfPageSize.A5;
case "A6":
return PdfPageSize.A6;
case "A7":
return PdfPageSize.A7;
case "A8":
return PdfPageSize.A8;
case "A9":
return PdfPageSize.A9;
case "ArchA":
return PdfPageSize.ArchA;
case "ArchB":
return PdfPageSize.ArchB;
case "ArchC":
return PdfPageSize.ArchC;
case "ArchD":
return PdfPageSize.ArchD;
case "ArchE":
return PdfPageSize.ArchE;
case "B0":
return PdfPageSize.B0;
case "B1":
return PdfPageSize.B1;
case "B2":
return PdfPageSize.B2;
case "B3":
return PdfPageSize.B3;
case "B4":
return PdfPageSize.B4;
case "B5":
return PdfPageSize.B5;
case "Flsa":
return PdfPageSize.Flsa;
case "HalfLetter":
return PdfPageSize.HalfLetter;
case "Ledger":
return PdfPageSize.Ledger;
case "Legal":
return PdfPageSize.Legal;
case "Letter":
return PdfPageSize.Letter;
case "Letter11x17":
return PdfPageSize.Letter11x17;
case "Note":
return PdfPageSize.Note;
default:
return PdfPageSize.A4;
}
}
private PdfPageOrientation SelectedPdfPageOrientation(string selectedValue)
{
return selectedValue == "Portrait" ? PdfPageOrientation.Portrait : PdfPageOrientation.Landscape;
}
}
}