Integrate WebViewer into Node.js and Enable Saving and Loading PDF Annotations

In addition to showing how to add the WebViewer component to a Node.js backend project, this sample expands on annotation functionality by enabling saving and loading the annotation objects into a PDF document.

The saving is done through POST HTTP message that is handled by an annotationHandler in the project.

Follow these steps:

  1. Create annotations with annotations tools in the header.
  2. Save annotations with the save button in the header.
  3. Load annotations by refreshing the app.
  4. Locate the original PDF document in server folder where the new annotations are saved into.

WebViewer provides a slick out-of-the-box responsive UI that enables you to view, annotate and manipulate PDFs and other document types inside any web project.

Click the button below to view the full project in GitHub.

1const viewerElement = document.getElementById('viewer');
2WebViewer({
3 path: 'lib',
4 initialDoc: 'https://pdftron.s3.amazonaws.com/downloads/pl/demo.pdf',
5}, viewerElement).then(instance => {
6 const {documentViewer, annotationManager} = instance.Core;
7
8 // Add a save button on header
9 const topHeader = instance.UI.getModularHeader('default-top-header');
10 const items = topHeader.getItems();
11
12 const saveButton = {
13 type: 'customButton',
14 img: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M17 3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2V7l-4-4zm-5 16c-1.66 0-3-1.34-3-3s1.34-3 3-3 3 1.34 3 3-1.34 3-3 3zm3-10H5V5h10v4z"/></svg>',
15 title: 'Save Annotations',
16 onClick: function() {
17 // Update the document when button is clicked
18 saveDocument('demo.pdf').then(function() {
19 alert('Annotations saved to the document.');
20 });
21 }
22 };
23
24 items.push(saveButton);
25 topHeader.setItems(items);
26
27 // Make a POST request with blob data for a PDF with new annotations
28 const saveDocument = function(filename) {
29 return new Promise(function(resolve) {
30 annotationManager.exportAnnotations().then(function(xfdfString) {
31 documentViewer.getDocument().getFileData({ xfdfString }).then(function(data) {
32 const arr = new Uint8Array(data);
33 const blob = new Blob([ arr ], { type: 'application/pdf' });
34 // FormData is used to send blob data through fetch
35 const formData = new FormData();
36 formData.append('blob', blob);
37 fetch(`/server/annotationHandler.js?filename=${filename}`, {
38 method: 'POST',
39 body: formData
40 }).then(function(res) {
41 if (res.status === 200) {
42 resolve();
43 }
44 });
45 });
46 });
47 });
48 };
49});
50

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales