Here's a guide on generating PDF or image files from HTML using wkhtmltopdf in C#. This method is widely used due to wkhtmltopdf’s capability to handle complex HTML, CSS, and even JavaScript, producing high-quality PDFs or images.
1. Setting Up wkhtmltopdf
wkhtmltopdf is a command-line tool that converts HTML to PDF and images using Webkit. Before integrating it with C#, you’ll need to.
- Download wkhtmltopdf from the official site.
- Install it on your machine and note the installation path (usually C:\Program Files\wkhtmltopdf on Windows).
2. Creating a C# Wrapper Engine for wkhtmltopdf
In C#, you can call wkhtmltopdf using System.Diagnostics.Process to execute command-line arguments. Here’s a basic implementation.
- Interface for Convert Items
- Process Path will be exe path of Engine
- Engine Type will be 1-> PDF Engine, 2-> Image Engine If we need more we can add future.
public interface IConverterWebKitEngine
{
string ProcessPath { get; }
int EngineType { get; }
bool ConvertContent(string inputPath, string outputPath);
}
- PDF Engine Implementation.
public class PDFConsoleConverter : IConverterWebKitEngine
{
private readonly ILogger<PDFConsoleConverter> _logger;
private readonly IWebHostEnvironment _hostingEnvironment;
public string ProcessPath { get; }
public int EngineType { get; } = 1;
public PDFConsoleConverter(ILogger<PDFConsoleConverter> logger, IWebHostEnvironment hostingEnvironment)
{
_logger = logger;
_hostingEnvironment = hostingEnvironment;
ProcessPath = _hostingEnvironment.WebRootPath + @$"\Tool\wkhtmltopdf.exe";
}
public bool ConvertContent(string inputPath, string outputPath)
{
try
{
var ticks = DateTime.UtcNow.Ticks;
string switches = "";
#region headers
switches += "--header-center wkhtmltopdf ";
switches += "--header-line ";
switches += "--header-spacing 5 ";
#endregion
#region general
switches += "--print-media-type ";
switches += "--margin-top 40mm --margin-bottom 10mm --margin-right 10mm --margin-left 10mm ";
switches += "--page-size A4 ";
#endregion
#region footer
switches += "--footer-line ";
switches += "--footer-center \"[page] of [topage]\" ";
#endregion
string processPdfpath = ProcessPath;
Process process = new Process();
process.StartInfo.UseShellExecute = true;
process.StartInfo.FileName = processPdfpath;
process.StartInfo.Arguments = $"{switches} \"{inputPath}\" \"{outputPath}\" ";
process.Start();
}
catch (Exception ex)
{
_logger.LogCritical(ex.Message);
return true;
}
return true;
}
}
- Image Engine Implementation.
public class ImageConsoleConverter : IConverterWebKitEngine
{
private readonly ILogger<ImageConsoleConverter> _logger;
private readonly IWebHostEnvironment _hostingEnvironment;
public string ProcessPath { get; }
public int EngineType { get; } = 2;
public ImageConsoleConverter(ILogger<ImageConsoleConverter> logger, IWebHostEnvironment hostingEnvironment)
{
_logger = logger;
_hostingEnvironment = hostingEnvironment;
ProcessPath = _hostingEnvironment.WebRootPath + @$"\Tool\wkhtmltoimage.exe";
}
public bool ConvertContent(string inputPath, string outputPath)
{
try
{
var ticks = DateTime.UtcNow.Ticks;
string processPdfpath = ProcessPath;
Process process = new Process();
process.StartInfo.UseShellExecute = true;
process.StartInfo.FileName = processPdfpath;
process.StartInfo.Arguments = $"\"{inputPath}\" \"{outputPath}\" ";
process.Start();
}
catch (Exception ex)
{
_logger.LogCritical(ex.Message);
return true;
}
return true;
}
}
- Using the Engine in Our Methods.
public class BussinessConstants
{
public static int ConvertEngineType_PDF = 1;
public static int ConvertEngineType_Image = 2;
}
[ApiController]
[Route("[controller]")]
public class FileConvertController : ControllerBase
{
private readonly ILogger<FileConvertController> _logger;
private readonly IWebHostEnvironment _hostingEnvironment;
private readonly IEnumerable<IConverterWebKitEngine> _converterWKs;
public FileConvertController(
ILogger<FileConvertController> logger,
IWebHostEnvironment hostingEnvironment,
IServiceProvider serviceScope)
{
_logger = logger;
_hostingEnvironment = hostingEnvironment;
_converterWKs = serviceScope.GetServices<IConverterWebKitEngine>();
}
[HttpGet("GetPDF")]
public IEnumerable<string> GetPDF()
{
var ticks = DateTime.UtcNow.Ticks;
var outputPdf = _hostingEnvironment.WebRootPath + $"\\OutputFiles\\Sync{ticks}.pdf";
string inputPath = _hostingEnvironment.WebRootPath + $"\\InputFiles\\Sync{ticks}.html";
string inputText =
"<html><head><title>Example of Paragraph tag</title></head><body style=\"line-height:1.6\">" +
"<p><b>HTML</b> stands for <i><u>Hyper Text Markup Language.</u></i> It is used to create " +
"web pages and applications. This language is easily understandable by the user and also " +
"modifiable. It is actually a Markup language, hence it provides a flexible way for designing " +
"the web pages along with the text.</p>HTML file is made up of different elements.<b>An element</b> " +
"is a collection of <i>start tag, end tag, attributes and the text between them</i>.<p></p>" +
"<h6>HTML to PDF / Image</h6><h5>HTML to PDF / Image</h5><h4>HTML to PDF / Image</h4>" +
"<h3>HTML to PDF / Image</h3><h2>HTML to PDF / Image</h2><h1>HTML to PDF / Image</h1></body></html>";
System.IO.File.WriteAllText(inputPath, inputText);
if (_converterWKs.Any())
{
IConverterWebKitEngine converterWK = _converterWKs.FirstOrDefault(x => x.EngineType == BussinessConstants.ConvertEngineType_PDF);
converterWK?.ConvertContent(inputPath, outputPdf);
}
return new List<string> { "A", "B" };
}
[HttpGet("GetImage")]
public IEnumerable<string> GetImage()
{
var ticks = DateTime.UtcNow.Ticks;
var outputImage = _hostingEnvironment.WebRootPath + $"\\OutputFiles\\Sync{ticks}.png";
string inputPath = _hostingEnvironment.WebRootPath + $"\\InputFiles\\Sync{ticks}.html";
string inputText =
"<html><head><title>Example of Paragraph tag</title></head><body style=\"line-height:1.6\">" +
"<p><b>HTML</b> stands for <i><u>Hyper Text Markup Language.</u></i> It is used to create " +
"web pages and applications. This language is easily understandable by the user and also " +
"modifiable. It is actually a Markup language, hence it provides a flexible way for designing " +
"the web pages along with the text.</p>HTML file is made up of different elements.<b>An element</b> " +
"is a collection of <i>start tag, end tag, attributes and the text between them</i>.<p></p>" +
"<h6>HTML to PDF / Image</h6><h5>HTML to PDF / Image</h5><h4>HTML to PDF / Image</h4>" +
"<h3>HTML to PDF / Image</h3><h2>HTML to PDF / Image</h2><h1>HTML to PDF / Image</h1></body></html>";
System.IO.File.WriteAllText(inputPath, inputText);
if (_converterWKs.Any())
{
IConverterWebKitEngine converterWK = _converterWKs.FirstOrDefault(x => x.EngineType == BussinessConstants.ConvertEngineType_Image);
converterWK?.ConvertContent(inputPath, outputImage);
}
return new List<string> { "A", "B" };
}
}
Notes. (Please ensure the below points).
- Ensure that the wkhtmltopdf.exe file is accessible by the C# application.
- wkhtmltopdf works best with HTML files that are fully self-contained (e.g., inline CSS and JavaScript).
- You may need to handle permissions if running on a server environment.
Conclusion
This method enables you to utilize wkhtmltopdf's rendering engine within C# applications, facilitating HTML-to-PDF and HTML-to-image conversions with high accuracy. With additional customization, you can modify this code to accommodate various document formats and needs.
Part 2: Converting HTML to PDF or Image in C# Using wkhtmltopdf Part 2 - Header & Footer