Quote of the Day

more Quotes

Categories

Get notified of new posts

Buy me coffee

Fill out a PDF form using iTextSharp for .NET core.

Published November 26, 2018 in .NET core - 4 Comments

iTextSharp is a popular library for working with PDF files. The  unofficial port of the v4.16 is available for .NET core. In this post, I show examples of using the library to programmatically read and fill out a PDF form.

The sample PDF form

For this post, I am using a simple PDF form consisting of the following fields: “First Name”, “Last Name”,  and a checkbox. By the way, if you haven’t created a PDF form before, one way to create a form is to use Microsoft Word to design the layout, save the file as a PDF and use Adobe Reader Pro to detect/add the fields.

Sample PDF form to show how to dynamically fill out a form using iTextSharp library for .NET core.
A simple PDF which we are going to fill out using iTextSharp library for .NET core.

Get the Library

In your .NET core or ASP.NET core application, add the iiTextSharp.LGPLv2.Core nuget package.

Per the documentation,

iTextSharp.LGPLv2.Core is an unofficial port of the latest LGPL version of the iTextSharp (V4.1.6) to .NET Core.

Get the fields in a PDF form using iTextSharp.

It is straightforward to get the fields using iTextSharp.

public ICollection GetFormFields(Stream pdfStream)
{
    PdfReader reader = null; 
    try 
    {
        PdfReader pdfReader = new PdfReader(pdfStream);
        AcroFields acroFields = pdfReader.AcroFields;
        return acroFields.Fields.Keys;
    }
    finally
    {
        reader?.Close(); 
    }
}

The above method reads the PDF content as a stream and return all the fields’ names.

Below is the test and the output of running the method with our simple PDF form.

Test:

/// <summary>
/// Test retrieving field names of a PDF form. 
/// @<see cref="IPDFFormService{T}.GetFormFields(System.IO.Stream)"/>
/// </summary>
[Fact]
public void GetFieldNames()
{
    Stream pdfStream = new FileStream(path:SamplePDFFilePath, 
                                      mode:FileMode.Open);
    ICollection fieldNames = samplePDFFormService.GetFormFields(pdfStream);
    foreach (var fieldName in fieldNames)
    {
        _output.WriteLine(fieldName.ToString());
    }
    pdfStream.Close();  

}

Output:

Running PDFFormFillingExample.PDFFormFillingExampleTests.PDFFormFillingExampleTests.Services.SamplePDFFormServiceTests.GetFieldNames ...
First Name
Awesome Checkbox
Last Name

Set the fields in a PDF form using iTextSharp

Below show the sample codes to fill out the sample PDF.

public Stream FillForm(Stream inputStream, PDFSampleForm model)
        {
            Stream outStream = new MemoryStream();
            PdfReader pdfReader = null;
            PdfStamper pdfStamper = null;
            Stream inStream = null; 
            try
            {
                pdfReader = new PdfReader(inputStream);
                pdfStamper = new PdfStamper(pdfReader, outStream);
                AcroFields form = pdfStamper.AcroFields;
                form.SetField(SampleFormFieldNames.FirstName, model.FirstName);
                form.SetField(SampleFormFieldNames.LastName, model.LastName);
                form.SetField(SampleFormFieldNames.IAmAwesomeCheck, model.AwesomeCheck ? "Yes" : "Off");
                // set this if you want the result PDF to not be editable. 
                pdfStamper.FormFlattening = true;
                return outStream; 
            }
            finally
            {
                pdfStamper?.Close();
                pdfReader?.Close();
                inStream?.Close(); 
            }
        }

The test below demonstrates calling the method to fill out the form and output the result to the file.

        /// <summary>
        /// Test setting values for the fields in a PDF.
        /// @<see cref="IPDFFormService{T}.FillForm(System.IO.Stream, T)"/>
        /// </summary>
        [Fact]
        public void FillForm()
        {
            PDFSampleForm sampleFormModel = new PDFSampleForm()
            {
                FirstName = "John",
                LastName = "Doe",
                AwesomeCheck = true

            };
            using (Stream pdfInputStream = new FileStream(path: "SamplePDFForm.pdf", mode: FileMode.Open))
            using(Stream resultPDFOutputStream = new FileStream(path: "SamplePDFFormFilled.pdf", mode: FileMode.Create))
            using(Stream resultPDFStream = _samplePDFFormService.FillForm(pdfInputStream, sampleFormModel))
            {
                // set the position of the stream to 0 to avoid corrupted PDF. 
                resultPDFStream.Position = 0; 
                _output.WriteLine(resultPDFStream.Position.ToString());
                resultPDFStream.CopyTo(resultPDFOutputStream);
            }
        }

Note:

It is necessary to set the position of the result PDF stream to 0 before consuming the stream (e.g. before outputting the stream to a file or returning the stream as a payload of a HTTP request). Otherwise, the result PDF is broken. 

Here is the result PDF which the above test produces.

The full sample project is available on GitHub.

4 comments