Passport Loader

Validating PDF/A documents using .NET and C#

Introduction

In this tutorial, we will learn how to validate a PDF/A file.
We will see how to verify its version and conformance level and modify them if needed.

You should have your machine already set up using instructions from our getting started guide.

The importance of PDF/A validation

PDF/A is the ISO standard for the long-term archiving of electronic documents (ISO 19000). It is also a complex format with many variations.
Because of its complexity, not all PDF/A converters are the same, and converted files may contain errors.

As long-term archiving is a crucial (and legal!) need for companies and organizations, it is important to be sure that the archived files are fully compliant and do not contain errors that could prevent their usage in the future. Also, it can be necessary to verify if a PDF/A document is saved under a specific version (1, 2, 3, 4) and conformance level (a, b, u, e, f). It is why validation is necessary.

The PDF/A standard evolves with time. As it is a subset of PDF, each new PDF version release requires an update of the format:

  • PDF/A-1 (a & b), ISO 19005-1:2005 - based on PDF 1.4.
  • PDF/A-2 (a, b & u), ISO 19005-2:2011 - based on PDF 1.7.
  • PDF/A-3 (a, b & u), ISO 19005-3:2012 - based on PDF 1.7.
  • PDF/A-4 (e & f), ISO 19005-4:2020 - based on PDF 2.0.

You can read more about the features of each version and conformance level on the AvePDF Blog articles about PDF/A conversion and PDF/A-4 (the AvePDF web app is built with PassportPDF).

PDF/A, just like PDF, is built to keep backward compatibility with earlier versions. Once a file is saved as PDF/A, it is valid and considered compliant, even if newer versions are released. In most cases, you shouldn’t need to update it to the latest standard version.

However, in some contexts (like when creating hybrid invoices that require the use of PDF/A-3), it is necessary to verify and modify the version and the conformance level.

How to use PassportPDF API and .NET to validate a PDF/A file

Now, we’re going to cover how to use PassportPDF API to check the version and conformance level of a PDF/A file. We will convert that file if it does not correspond to what we need.

We will use the following endpoints:

  • DocumentLoadFromURIAsync to load a document from a URI.
  • ValidatePDFA to identify the version and conformance level of a PDF/A file.
  • ConvertToPDFA to convert the PDF/A file to the desired version.

The code below illustrates how to use these endpoints to validate if a PDF/A corresponds to PDF/A-3u. If not, then we convert it to PDF/A-3u.

using PassportPDF.Api;
using PassportPDF.Client;
using PassportPDF.Model;

namespace DocumentConversion
{

    public class DocumentConverter
    {
        static async Task Main(string[] args)
        {
            GlobalConfiguration.ApiKey = "YOUR-PASSPORT-CODE";

            PassportManagerApi apiManager = new();
            PassportPDFPassport passportData = await apiManager.PassportManagerGetPassportInfoAsync(GlobalConfiguration.ApiKey);

            if (passportData == null)
            {
                throw new ApiException("The Passport number given is invalid, please set a valid passport number and try again.");
            }
            else if (passportData.IsActive is false)
            {
                throw new ApiException("The Passport number given not active, please go to your PassportPDF dashboard and active your plan.");
            }

            string uri = "https://passportpdfapi.com/test/pdfa_file.pdf";

            DocumentApi api = new();

            Console.WriteLine("Loading document into PassportPDF...");
            DocumentLoadResponse document = await api.DocumentLoadFromURIAsync(new LoadDocumentFromURIParameters(uri));
            Console.WriteLine("Document loaded.");

            PDFApi pdfApi = new();


            // Check if PDF/A conformance level is PDFA3u
            Console.WriteLine("Checking if conformance level of PDF/A file is PDF/A-3u ...");

            PdfValidatePDFAResponse pdfValidatePdfaResponse = await pdfApi.ValidatePDFAAsync(new PdfValidatePDFAParameters(document.FileId)
            {
                Conformance = PdfAValidationConformance.Autodetect
            });

            if (pdfValidatePdfaResponse.Error is not null)
            {
                throw new ApiException(pdfValidatePdfaResponse.Error.ExtResultMessage);
            }
            else
            {
                Console.WriteLine("PDFA conformance level is : {0}", pdfValidatePdfaResponse.Conformance);

                if(pdfValidatePdfaResponse.Conformance == PdfAValidationConformance.PDFA3u)
                {
                    Console.WriteLine("Your PDF/A file has the right conformance level");
                }
                else
                {
                    Console.WriteLine("Your PDF/A file does NOT have the right conformance level. Running conversion process to have PDF/A-3u conformance level ...");

                    try
                    {
                        // Convert PDF/A to your chosen conformance level : PDFA3u
                        PdfConvertToPDFAResponse pdfConvertResponse = await pdfApi.ConvertToPDFAAsync(new PdfConvertToPDFAParameters(document.FileId)
                        {
                            Conformance = PdfAConformance.PDFA3u
                        });

                        if (pdfConvertResponse.Error is not null)
                        {
                            throw new ApiException(pdfConvertResponse.Error.ExtResultMessage);
                        }
                        else
                        {
                            Console.WriteLine("Conversion process finished successfully. Downloading the new PDF/A file ...");

                            // Download file with PDF/A-3u conformance level

                            PdfSaveDocumentResponse saveDocResponse = await pdfApi.SaveDocumentAsync(new PdfSaveDocumentParameters(document.FileId));

                            string savePath = Path.Join(Directory.GetCurrentDirectory(), "PDFA3u_file.pdf");

                            File.WriteAllBytes(savePath, saveDocResponse.Data);

                            Console.WriteLine("Done downloading PDF/A file. Document has been saved in : {0}", savePath);
                        }
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Could not convert or download new PDF/A file! Issue : {0}", ex.Message);
                    }
                }
            }
        }
    }
}

When the code finishes running, you will see an output like this:

As you can see when we first uploaded the document and we checked its conformance level, we found out that it was a PDF/A-2a. Since we wanted a PDF/A-3u, we needed to convert that file. After the conversion, we see that the document conformance level is now PDF/A-3u.

Final remarks

PassportPDF API helps you validate your PDF/A documents. With a few lines of code, you can check the version and conformance level of your PDF/A file and convert it to another version when necessary.

If the validation fails because the PDF/A input file contains too many errors, use our PDF/A converter to generate an error-free PDF/A file.

For more information about the endpoints used in this tutorial, please visit the PassportPDF API reference.