PDF.js Express Plusplay_arrow

Professional PDF.js Viewing & Annotations - Try for free

side menu

Get Started

play_arrow

Learn more

play_arrow

Common use cases

play_arrow

Open a document

play_arrow

Save a document

play_arrow

Viewer

play_arrow

UI Customization

play_arrow

Annotations

play_arrow

Collaboration

play_arrow

Forms

play_arrow

Signature

play_arrow

Searching

play_arrow

Measurement

play_arrow

Compare

play_arrow

Advanced Capabilities

play_arrow

PDF.js Express REST API

play_arrow

Migration Guides

play_arrow

XFDF format

The following features are available in:

check

PDF.js Express Viewer

help_outline

PDF.js Express Viewer is a free viewer with limited capabilities compared to PDF.js Express Plus

check

PDF.js Express Plus

help_outline

PDF.js Express Plus is a commercial PDF SDK for viewing, annotating, signing, form filling and more

According to the XFDF specification:

XFDF (XML Forms Data Format) is a format for representing forms data and annotations in a PDF document. XFDF is the XML version of Forms Data Format (FDF), a simplified version of PDF for representing forms data and annotations.

Examples

<?xml version="1.0" encoding="UTF-8" ?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
  <fields>
    <field name="ACombo"><value>Red</value></field>
  </fields>
  <annots>
    <square subject="Rectangle" page="0" rect="306.01,744.85,408.98,775.94" flags="print" name="447c49b7-5e50-4b13-adc8-c291102466e6" title="Guest" date="D:20171226120150-08'00'" color="#000000" width="5" creationdate="D:20171226120147-08'00'">
      <popup flags="print,nozoom,norotate" page="0" rect="0,767,112.5,842" open="no"/>
    </square>
  </annots>
</xfdf>

The fields section contains the names and values of any form fields in the document. In annots all of the annotation data is found.

In PDF.js Express Web Viewer

PDF.js Express provides methods to import annotations into the viewer from their XFDF data as well as export all currently loaded annotations as XFDF using AnnotationManager.

WebViewer(...)
  .then(instance => {
    const { annotManager } = instance; 
    // import asynchronously
    // you might call this after fetching the XFDF data as a string from your server
    annotManager.importAnnotations(xfdfData).then(importedAnnotations => { });

    // get all annotation and form data
    // you might call this when you want to pass the XFDF data to your server to be saved
    // or you may want to pass an XFDF string to doc.getFileData to embed the annotations
    // in the downloaded PDF
    annotManager.exportAnnotations().then(xfdfData => { });

    // if you're saving the XFDF to your server and calling importAnnotations when loading
    // you may not want to save the widgets and links if they won't be changing in the document
    // this is because widgets and links don't have unique ids so WebViewer isn't always able
    // to merge them together without duplicating them when calling importAnnotations
    // as long as you save the field values then changes made to the fields (e.g. checking a checkbox)
    // will be saved
    // if you don't need to save field values either you can use "fields: false"
    annotManager.exportAnnotations({
      widgets: false,
      links: false
      //fields: false
    }).then(annotData => { })

    // only get XFDF data for specified annotations
    // this might be useful if you save the XFDF data separately per user on your server
    // and you want to get the XFDF data for a particular user's annotations
    // it can also be useful if you want to get the XFDF for a particular annotation
    // because you're saving each annotation in a separate database row on your server
    annotManager.exportAnnotations({
      annotList: [annot1, annot2]
    }).then(annotData => { })
  })
WebViewer(...)
  .then(instance => {
    const { annotationManager } = instance.Core; 
    // import asynchronously
    // you might call this after fetching the XFDF data as a string from your server
    annotationManager.importAnnotations(xfdfData).then(importedAnnotations => { });

    // get all annotation and form data
    // you might call this when you want to pass the XFDF data to your server to be saved
    // or you may want to pass an XFDF string to doc.getFileData to embed the annotations
    // in the downloaded PDF
    annotationManager.exportAnnotations().then(xfdfData => { });

    // if you're saving the XFDF to your server and calling importAnnotations when loading
    // you may not want to save the widgets and links if they won't be changing in the document
    // this is because widgets and links don't have unique ids so WebViewer isn't always able
    // to merge them together without duplicating them when calling importAnnotations
    // as long as you save the field values then changes made to the fields (e.g. checking a checkbox)
    // will be saved
    // if you don't need to save field values either you can use "fields: false"
    annotationManager.exportAnnotations({
      widgets: false,
      links: false
      //fields: false
    }).then(annotData => { })

    // only get XFDF data for specified annotations
    // this might be useful if you save the XFDF data separately per user on your server
    // and you want to get the XFDF data for a particular user's annotations
    // it can also be useful if you want to get the XFDF for a particular annotation
    // because you're saving each annotation in a separate database row on your server
    annotationManager.exportAnnotations({
      annotList: [annot1, annot2]
    }).then(annotData => { })
  })

PDF.js Express also provides a way to get the XFDF data for annotations that have changed recently in the viewer. AnnotationManager.exportAnnotCommand will get the XFDF data for annotations that have been added, modified or deleted since the last time exportAnnotCommand was called.

A command looks something like this:

<?xml version="1.0" encoding="UTF-8" ?>
<xfdf xmlns="http://ns.adobe.com/xfdf/" xml:space="preserve">
<fields />
<add>
  <text subject="Comment" page="0" rect="262.13,465.90,285.38,489.15" flags="print,nozoom,norotate" name="651eab92-9258-f676-b5c0-9767cb1ab932" title="Guest" date="D:20171226125004-08'00'" color="#FFFF00" opacity="0.5" creationdate="D:20171226125004-08'00'" icon="Comment">
    <popup flags="print,nozoom,norotate" page="0" rect="0,573,112.5,648" open="no"/>
  </text>
</add>
<modify>
  <text subject="Comment" page="0" rect="110.47,367.84,133.72,391.09" flags="print,nozoom,norotate" name="e89d6405-fdcc-aa2b-9ebb-cc9d8a525ca2" title="Guest" date="D:20171226125247-08'00'" color="#FFFF00" opacity="0.5" creationdate="D:20171226125238-08'00'" icon="Comment">
    <popup flags="print,nozoom,norotate" page="0" rect="0,573,112.5,648" open="no"/>
  </text>
</modify>
<delete>
  <id page="0">e2976b7b-075b-cad9-0f9f-fe0de613a543</id>
</delete>
</xfdf>

Commands can be imported using AnnotationManager.importAnnotCommand. This is the technique that is used in the realtime collaboration example.

To merge annotations directly into the document PDF.js Express offers a REST API. This can also be used when importing pre-existing annotation made within a PDF.