Save Annotations to External Storage
You have two options to save annotation changes to external storage: saving the changes only, or saving the whole PDF.
Saving the Changes Only
Our recommendation for storing changes to annotations is through Instant JSON. Importing and exporting a JSON file with the changes made to a document instead of doing this with the full PDF each time significantly reduces the bandwidth used.
If you just want to save the annotation changes made by the user on the original PDF, you can use Instance#exportInstantJSON
to export a JSON containing all the changes. You can store this separately and apply it when you load the original PDF next time using Configuration#instantJSON
(Standalone mode only). With this approach, you won’t have to repeatedly save the PDF file, and you can use the original PDF every time.
Please see the importing and exporting section of our Instant JSON reference guide for examples of how to use Instant JSON.
When using the Server-Backed mode, you can still use Instance#exportInstantJSON()
to export annotation changes to external storage. Follow the Server-Backed guides for an in-depth example of how to use Instant JSON in Server-Backed mode.
Saving the Whole PDF
You can export the modified PDF as an array buffer by using Instance#exportPDF
and triggering a download, as explained in the Save a Document to Local Storage guide.
Ensuring Annotations Have Been Persisted
If you want to ensure that an annotation has been persisted by the backend, you can use the Instance.ensureChangesSaved
endpoint. This endpoint takes an array of changes and returns a promise that resolves to the array of changes in their persisted state as soon as they’re saved by the server. This means if you update the annotation before it has been saved by the server, Instance.ensureChangesSaved
will return the updated annotation, even though Instance.ensureChangesSaved
might have been called before the annotation was updated. Since this method takes exactly the same argument that’s returned by the
Instance#create
method, you can easily chain the calls. The ID can be used with the backend API and is unique inside a document:
PSPDFKit.load(configuration).then(async (instance) => { const createdAnnotations = await instance.create(newAnnotation); const [savedAnnotation] = await instance.ensureChangesSaved( createdAnnotations ); console.log(savedAnnotation.id); // => '01BS964AM5Z01J9MKBK64F22BQ' });
PSPDFKit.load({ ...configuration, autoSaveMode: PSPDFKit.AutoSaveMode.DISABLED }).then(async (instance) => { const newAnnotation = new PSPDFKit.Annotations.TextAnnotation({ pageIndex: 0, boundingBox: new PSPDFKit.Geometry.Rect({ left: 100, top: 200, width: 150, height: 75 }), text: { format: "plain", value: "foo" } }); console.log(newAnnotation.text); // => 'foo' const createdAnnotations = await instance.create(newAnnotation); const savedAnnotationPromise = instance.ensureChangesSaved( createdAnnotations ); const updatedAnnotations = await instance.update( createdAnnotations[0].set("text", "bar") ); instance.save(); const [savedAnnotation] = await savedAnnotationPromise; console.log(savedAnnotation.text); // => 'bar' });