> For the complete documentation index, see [llms.txt](https://docs.apryse.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.apryse.com/web/get-started/samples/showcase-demo-validate-pdfa.md).

# Validate PDF/A - Showcase Demo

Validate a PDF/A for long term storage by checking whether it meets the ISO19005 standard. Use the showcase demo related to this code sample.

{% hint style="info" %}
**Requirements**

*These packages are required to use these features in production. Trial keys have unlimited access to all features*

<a href="/web/get-started/readme.md" class="button primary">Web SDK</a><a href="https://apryse.com/capabilities#Archive" class="button primary">Package: Archive</a><a href="https://showcase.apryse.com/validate-pdfa" class="button primary">Live demo</a>
{% endhint %}

Quickly determine whether a PDF/A is fully compliant with the [international standard ISO 19005:1/2/3/4](https://en.wikipedia.org/wiki/PDF/A). In case of non-compliance, you will obtain a detailed report of violations with a list of relevant error objects.

PDF/A is an ISO-standardized version of the Portable Document Format (PDF) specialized for use in the archiving and long-term preservation of electronic documents. PDF/A differs from PDF by prohibiting features unsuitable for long-term archiving, such as font linking (as opposed to font embedding) and encryption.

This demo allows you to:

* Choose your own PDF file to validate
* Check specification compliance to ISO 19005:1/2/3/4
* Produce a results report
* Customize compliance checks
* Validate whether a PDF/A file is safe for long term storage

### **Implementation steps**

To add PDF/A validation capability with WebViewer:

Step 1: Follow [get started in your preferred web stack for WebViewer](/web/get-started/readme.md) Step 2: Add the ES6 JavaScript sample code provided in this guide

Once you generate your license key, it will automatically be included in your sample code below.

{% @apryse-license-key/apryse-license-key platform="WEB\_VIEWER" variant="compact" %}

<pre class="language-js" data-line-numbers><code class="lang-js">/*
ES6 Compliant Syntax
GitHub Copilot, Version 1.0, Model GPT-4, 2024-06-09
File: validate-pdfa/index.js
*/

import WebViewer from '@pdftron/webviewer';

const licenseKey = '<code class="expression">visitor.claims.wvKey || "YOUR_WEBVIEWER_LICENSE_KEY"</code>';


const element = document.getElementById('viewer');
let theInstance = null;
const onLoad = async (instance) => {
  theInstance = instance;
};

WebViewer(
  {
    path: '/lib',
    licenseKey: licenseKey, 
    initialDoc: 'https://apryse.s3.us-west-1.amazonaws.com/public/files/samples/pdfa.pdf',
    fullAPI: true, // Enable full API access to use validation features
  },
  element
).then((instance) => {
  onLoad(instance);
});

const pdfaLevels = [
  { label: 'PDF/A-1A', value: '1A' },
  { label: 'PDF/A-1B', value: '1B' },

  { label: 'PDF/A-2A', value: '2A' },
  { label: 'PDF/A-2B', value: '2B' },
  { label: 'PDF/A-2U', value: '2U' },

  { label: 'PDF/A-3A', value: '3A' },
  { label: 'PDF/A-3B', value: '3B' },
  { label: 'PDF/A-3U', value: '3U' },

  { label: 'PDF/A-4', value: '4' },
  { label: 'PDF/A-4E', value: '4E' },
  { label: 'PDF/A-4F', value: '4F' },
];

// Validate PDF/A compliance
// This is the main function, which checks the PDF/A compliance of the currently loaded document
async function validatePdfa() {
  let validResult = ""; // Replace with actual validation logic
  const documentViewer = theInstance.Core.documentViewer;

  const xfdfString = await theInstance.Core.annotationManager.exportAnnotations();
  const currentDocument = documentViewer.getDocument();
  const data = await currentDocument.getFileData({
      xfdfString,
      flags: theInstance.Core.SaveOptions.INCREMENTAL,
    });

  if(currentDocument.type !== 'pdf') {
    labelStatus.textContent = '❌ Cannot validate PDF/A compliance. This document is not a PDF.';
    labelStatus.style.backgroundColor = 'lightcoral';
    return;
  }
  const pdfDoc = await currentDocument.getPDFDoc();
  let pdfaVersion = await theInstance.Core.PDFNet.PDFACompliance.getDeclaredConformance(pdfDoc) - 1;
  if(pdfaVersion === -1)
    pdfaVersion = 0; // Default to PDF/A-1A if no conformance is declared

  console.log(`PDF/A Version: ${pdfaVersion}`);
  const conformanceLevel = theInstance.Core.PDFNet.PDFACompliance.Conformance[`e_Level${pdfaLevels[pdfaVersion].value}`];

  const pdfa = await theInstance.Core.PDFNet.PDFACompliance.createFromBuffer(
    false,
    new Uint8Array(data),
    '',
    conformanceLevel
  );

  const errorCount = await pdfa.getErrorCount();
  if (errorCount === 0) {
    validResult = "✅ PDF/A Validation Successful. ";
    validResult += `Standard: ${pdfaLevels[pdfaVersion].label}. `;
    validResult += `Conformance Level: ${pdfaLevels[pdfaVersion].value}`;
    labelStatus.style.backgroundColor = 'lightgreen';
    } else {
      labelStatus.style.backgroundColor = 'lightcoral';
      validResult = "❌ PDF/A Validation Failed. This document is not a PDF/A.";
    }

  labelStatus.textContent = validResult;
}

const buttonValidate = document.createElement('button');
buttonValidate.textContent = 'Validate PDF/A';
buttonValidate.onclick = async () => {
  validatePdfa();
};

const buttonUpload = document.createElement('button');
buttonUpload.textContent = 'Upload Local PDF';
buttonUpload.onclick = async () => {
  fileUpload.click();
};

const labelStatus = document.createElement('label');
labelStatus.textContent = `Click "${buttonValidate.textContent}" to validate the PDF/A compliance of the document.`;

// UI section
//
// Helper code to add controls to the viewer holding the buttons and dropdown
// This code creates a container for the buttons and dropdown, styles them, and adds them to the viewer


// Create a container for all controls (file input buttons)
const controlsContainer = document.createElement('div');

const fileUpload = document.createElement('input');
fileUpload.style.display = 'none';
fileUpload.type = 'file';
fileUpload.accept = '.pdf';
fileUpload.onchange = (event) => {
  const file = event.target.files[0];
  if (file) {
    labelStatus.style.backgroundColor = '';
    labelStatus.textContent = `Loading document: ${file.name}`;
    const reader = new FileReader();
    reader.onload = () => {
      theInstance.UI.loadDocument(reader.result, {filename: file.name});
    };
    reader.readAsArrayBuffer(file);
  }
};

buttonUpload.className = 'btn-style';
buttonValidate.className = 'btn-style';
labelStatus.className = 'label-status';
controlsContainer.className = 'button-container';
controlsContainer.appendChild(fileUpload);
controlsContainer.appendChild(buttonUpload);
controlsContainer.appendChild(buttonValidate);
controlsContainer.appendChild(labelStatus);
element.insertBefore(controlsContainer, element.firstChild);
</code></pre>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.apryse.com/web/get-started/samples/showcase-demo-validate-pdfa.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
