Some test text!

Search
Hamburger Icon

Web / Guides

Import/export annotations

There are a few ways to import or export annotations such as from a file, a database, or a document. There are also more advanced loading options to help with finer control of the data.

Importing and exporting annotations using a database

Another option is to use a database to store XFDF. You can choose to store the XFDF string for the document and user as described in using files , but with a database you can store and organize the XFDF data so that the XFDF string for each annotation is separate, allowing you to update it individually instead of updating the entire XFDF file for every change. For example, you can store and organize XFDF strings based on a combination of factors like document ID, annotation ID, author, etc.

For example, with a relational database, you can have a table called Annotations which contains annotation ID, document ID and xfdfString columns. In this setup, you can fetch all annotations for a particular document, or just fetch one annotation you are interested in.

Saving annotations using a database

Export annotation command XFDF

To save individual annotations separately, the exportAnnotationCommand and annotationChanged event are very useful. exportAnnotationCommand returns XFDF data for all of the annotations that have changed since the last time you called exportAnnotationCommand.

Annotations that have been added are inside the add element, modified annotations are in the modify element and deleted annotations have their ID inside the delete element of the XFDF. If you call this function on the annotationChanged event, you can POST each command to your server to save each annotation change as it happens as opposed to having your user press a save button.

WebViewer(...)
  .then(instance => {
    const { annotationManager } = instance.Core;

    // Save the annotation XFDF as a transaction command for every change
    annotationManager.addEventListener('annotationChanged', async (annotations, action, { imported }) => {
      // If the event is triggered by importing then it can be ignored
      // This will happen when importing the initial annotations
      // from the server or individual changes from other users
      if (imported) return;

      const xfdfString = await annotationManager.exportAnnotationCommand();
      // <xfdf>
      //   <add>
      //     <text subject="Comment" page="0" color="#FFE6A2" ... />
      //   </add>
      //   <modify />
      //   <delete />
      // </xfdf>
      fetch('path/to/annotation/server', {
        method: 'POST',
        body: xfdfString // written to a database in the server
      });
    });
    // Full samples are available at the end of this section.
  });

Import annotation command XFDF

When importing annotations, you can use importAnnotationCommand. The earliest point you can call this is during documentLoaded.

WebViewer(...)
  .then(instance => {
    const { documentViewer, annotationManager } = instance.Core;

    documentViewer.addEventListener('documentLoaded', () => {
      // load the annotation data as a transaction command
      fetch('path/to/annotation/server', {
        method: 'GET'
      }).then(async response => {
        if (response.status === 200) {
          response.text().then(xfdfString => {
            // <xfdf>
            //   <add>
            //     <text subject="Comment" page="0" color="#FFE6A2" ... />
            //   </add>
            //   <modify />
            //   <delete />
            // </xfdf>
            const annotations = await annotationManager.importAnnotationCommand(xfdfString);
            annotations.forEach(a => {
              annotationManager.redrawAnnotation(annotation);
            });
          });
        }
        // Full samples are available at the end of this section.
      });
    });
  });

At this point you'll be saving annotations in realtime, so if you want to have a fully realtime solution you'll need to update annotations on each client in realtime. You can extend realtime saving further by hooking it up to a WebSocket, which can broadcast the new xfdfString in the database to be imported to all the clients. By utilizing exportAnnotationCommand instead of exportAnnotations you can greatly reduce the size of the data being transferred to/from the annotation server.

For samples about saving annotations into different databases, see links below:

Trial setup questions? Ask experts on Discord
Need other help? Contact Support
Pricing or product questions? Contact Sales