How to generate a PDF from HTML using wkhtmltopdf with C# in WinForms

How to generate a PDF from HTML using wkhtmltopdf with C# in WinForms

For web developers, it's a lot easier to create a PDF from the HTML format, basically because it provides a better option to manage the PDF. For this task, the web developers use libraries like wkhtmltopdf. wkhtmltopdf is a command line tools to render HTML into PDF using the QT Webkit rendering engine. These run entirely "headless" and do not require a display or display service.

In this article, you will learn how to use wkhtmltopdf easily with C# in your Windows Forms application.

Requirements

  • You will need Visual Studio with NuGet Package Manager (>=2010).

In our case, we are going to use Visual Studio Community, so let's get started !

1. Install Pechkin

To generate a PDF from a HTML file with C# in Windows Forms, we are going to use Pechkin, the .NET Wrapper for wkhtmltopdf DLL, library that uses Webkit engine to convert HTML pages to PDF. Pechkin is available as a NuGet package, in most cases you should use SynchronizedPechkin as it protects multithreaded code from crashing the lib. But for simple usage from one thread, you can use SimplePechkin directly.

Note

Pechkin includes the latest version of wkhtmltox DLL in the project (and in NuGet package) along with its dependencies, and copied into build folder on project build. So there's no need to install any prerequisites before using the library on the computer.

Install the package with Visual Studio, by accessing the NuGET package manager. Do right click in your project in the Solution Explorer at the right top of Visual Studio and select Manage NuGet packages in the dropdown menu:

Solution explorer nuget packages

Now from the emergent window search for the Pechkin.Synchronized package, select it and install it in your project:

Pechkin.Synchronized NuGET package visual studio

Once the setup finishes, you will be able to use the wrapper in your project.

2. Generate a PDF

The Convert method converts a HTML string (or a configuration object) to PDF with the given settings and returns a byte arrays that store the binary data of the PDF.

Note

With all the examples, the pdfContent variable will generate only the content of the PDF and you won't see anything, therefore don't forget to write the created content into a file by following the step #3.

A. Generate simple PDF from a HTML string

You can create a PDF quickly with an empty global configuration object. Import the Pechkin type in your class:

using Pechkin;

And then create the content of the PDF with the following snippet:

byte[] pdfContent = new SimplePechkin(new GlobalConfig()).Convert("<html><body><h1>Hello world!</h1></body></html>");

B. Generate PDF from a Website

Instead of a plain HTML string, you can render a website through it's URL with the SetPageUri method in the configuration. Import the Pechkin.Synchronized type at the top of your class:

using Pechkin.Synchronized;

And then use the following code to create a PDF from a website:

// create global configuration object
GlobalConfig gc = new GlobalConfig();

// set it up using fluent notation
// Remember to import the following type:
//     using System.Drawing.Printing;
//
// a new instance of Margins with 1-inch margins.
gc.SetMargins(new Margins(100, 100, 100, 100))
    .SetDocumentTitle("Test document")
    .SetPaperSize(PaperKind.Letter)
    // Set to landscape
    //.SetPaperOrientation(true)
;

// Create converter
IPechkin pechkin = new SynchronizedPechkin(gc);

// Create document configuration object
ObjectConfig configuration = new ObjectConfig();

// and set it up using fluent notation too
configuration.SetCreateExternalLinks(false)
    .SetFallbackEncoding(Encoding.ASCII)
    .SetLoadImages(true)
    .SetPageUri("http://ourcodeworld.com");

// Generate the PDF with the given configuration
// The Convert method will return a Byte Array with the content of the PDF
// You will need to use another method to save the PDF (mentioned on step #3)
byte[] pdfContent = pechkin.Convert(configuration);

C. Generate PDF from a local HTML file

To create a PDF from a local HTML file, you can do it by providing the local filepath of the file with the SetPageUri method (in the same way that you do with a website) but at the same time, allow the usage of local resources with the SetAllowLocalContent method (note that you need to append as prefix file:/// to the html filepath). Import the Pechkin.Synchronized type at the top of your class:

using Pechkin.Synchronized;

And use the following code to create a PDF from a local HTML file:

// create global configuration object
GlobalConfig gc = new GlobalConfig();

// set it up using fluent notation
// Remember to import the following type:
//     using System.Drawing.Printing;
//
// a new instance of Margins with 1-inch margins.
gc.SetMargins(new Margins(100, 100, 100, 100))
    .SetDocumentTitle("Test document")
    .SetPaperSize(PaperKind.Letter);

// Create converter
IPechkin pechkin = new SynchronizedPechkin(gc);

// Create document configuration object
ObjectConfig configuration = new ObjectConfig();


string HTML_FILEPATH = "C:/Users/sdkca/Desktop/example.html";

// and set it up using fluent notation too
configuration
.SetAllowLocalContent(true)
.SetPageUri(@"file:///" + HTML_FILEPATH);

// Generate the PDF with the given configuration
// The Convert method will return a Byte Array with the content of the PDF
// You will need to use another method to save the PDF (mentioned on step #3)
byte[] pdfContent = pechkin.Convert(configuration);

Now that you know how to generate the content of a PDF, you only need to learn how to save it.

3. Save the PDF

As mentioned previously, Pechkin generates a PDF and return the data as a byte array, that means that you will need to write that data somehow by yourself. We will write the PDF into a file using the FileStream class included in the assembly System.IO. With FileStream you can read from, write to, open, and close files on a file system, as well as to manipulate other file related operating system handles including pipes, standard input, and standard output. Before using it, import the following type with the using directive in the top of your class:

using System.IO;

And then, use the class to create a file with the returned ByteArray as content. You can use the following method that expects as first parameter the absolute path of the file and as second parameter the data to write (pdf content):

/// <summary>
/// Writes a byte array (format returned by SimplePechkin) into a file
/// </summary>
/// <param name="_FileName"></param>
/// <param name="_ByteArray"></param>
/// <returns></returns>
public bool ByteArrayToFile(string _FileName, byte[] _ByteArray)
{
    try
    {
        // Open file for reading
        FileStream _FileStream = new FileStream(_FileName, FileMode.Create, FileAccess.Write);
        // Writes a block of bytes to this stream using data from  a byte array.
        _FileStream.Write(_ByteArray, 0, _ByteArray.Length);

        // Close file stream
        _FileStream.Close();

        return true;
    }
    catch (Exception _Exception)
    {
        Console.WriteLine("Exception caught in process while trying to save : {0}", _Exception.ToString());
    }
    
    return false;
}

Then it can be used as shown in the following example:

// Simple PDF from String
byte[] pdfBuffer = new SimplePechkin(new GlobalConfig()).Convert("<html><body><h1>Hello world!</h1></body></html>");

// Folder where the file will be created 
string directory = "C:\\Users\\sdkca\\Desktop\\";
// Name of the PDF
string filename = "hello_world.pdf";

if (ByteArrayToFile(directory + filename, pdfBuffer))
{
    Console.WriteLine("PDF Succesfully created");
}
else
{
    Console.WriteLine("Cannot create PDF");
}

Happy coding !

Become a more social person