We are using 8.7.4 version of PDF Express in our react code. We are facing an issue of the adding markup, mentioned below.
Generally when we add simple markups, it works fine, but when I add the measurements, those markups are not applied on the PDF file.
I am attaching the video URL along with the issue report. https://drive.google.com/file/d/1t088eB7ZshlqOGqe4hx4f05GmQqOqus9/view?usp=sharing
Looking forward to hearing from you.
Thanks & Regards
Expected behaviour
{Provide a screenshot or description of the expected behaviour}
Does your issue happen with every document, or just one?
{Answer here}
Link to document
{Provide a link to the document in question if possible}
I see the following snippet in your ‘getFileData’ method:
const getFileData = async (): Promise<PdfjsExpressPropsOnSaveValue> => {
// Get the annotations and the documents data
var xfdf = await instance.annotManager.exportAnnotations({
links: false,
widgets: false,
});
// Set the annotations and document into the Utility SDK, then merge them together
utils.setFile(config.file_path).setXFDF(xfdf);
const resp = await utils.merge(); // merge XFDF
// Get the resulting blob from the merge operation
var mergedBlob = await resp.getBlob();
return {
blobdata: mergedBlob,
xfdf,
};
};
But you are not actually calling the Document class’ getFileData, but your own getFileData method with the same name.
Could you please try the method shown in this guide and see if that works for you:
The issue is not related to the getFileData function currently in use. The problem specifically occurs within the annotationManager.importAnnotations method. We are successfully receiving the XFDF (annotation data) when exporting the annotations through the onSave function using exportAnnotations. However, when we attempt to reapply the same XFDF string using importAnnotations(xfdfString), the measurement annotations are not rendered in the document as expected.
We have also implemented the same approach suggested in your earlier comment, but the issue persists with the same behavior.
For your reference, we have attached a video demonstrating the problem, along with the exact XFDF string generated from exportAnnotations for the measurement annotations. Please verify this XFDF data and advise on a reliable solution to ensure proper import and rendering of these measurement annotations in the document.
Additional details that may be relevant:
- The document is fully loaded before calling importAnnotations.
- We have ensured that the same document is being used for both export and import.
- The annotations appear correctly in the original session before export.
- The XFDF contains valid measurement annotation entries.
- No errors are thrown during the importAnnotations call.
Kindly review and let us know if there are any known limitations, required configuration flags, or specific initialization steps needed for importing measurement annotations in PDF.js Express.
Thank you for confirming that your save button is exporting the annotation and you load the annotation when the document is fully loaded. This means you are not really going through the merge API to embed the annotations into the document, but importing it dynamically like this:
The issue is due to the element that was generated in the annotation. I recommend removing this from the XFDF and it should load as expected:
We tried the proposed solution, and it is functioning as expected. However, we have identified an additional issue: the units for each measurement are currently overlapping at the last rendered position. Instead, each unit should be displayed within its respective measurement. We kindly request a solution to address this issue.
It looks like removing the above custom data will remove the measurement for the annotation. Please keep the custom data information when exporting, and please try updating to version 8.7.5 of pdf.js express and see if that works for you.
Thank you for the details.
We are not permanently removing the custom data from the XFDF string during the export of annotation data; it is only temporarily removed during the import process. The complete XFDF string, including the custom data, is stored in the database. At the time of import, we dynamically replace the trn-custom-data value with a blank entry. Additionally, we attempted to resolve the issue by updating the version from 8.7.4 to 8.7.5; however, this update did not resolve the problem.
Below is the code that we have implemented for importing annotations. nothing else we are doing for importing feature.
docViewer.on(“documentLoaded”, async () => {
instance.UI.setFitMode(instance.FitMode.FitWidth);
const annotManager = instance.annotManager;
if (!config.annotation_data) return;
let xfdfString = config.annotation_data;
xfdfString = xfdfString
.replace(/\\\\"/g, '"')
.replace(/>\\s+</g, "><")
.replace(/<trn-custom-data\[^>\]\*\\/>/g, "");
try {
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xfdfString, "application/xml");
// Check if there were any errors while parsing XML
const parseError = xmlDoc.getElementsByTagName("parsererror");
if (parseError.length > 0) {
return;
}
// Serialize the XML document back to a string after modifications
const serializer = new XMLSerializer();
let updatedXmlString = serializer.serializeToString(xmlDoc);
// Ensure that the XFDF string is still valid (check if necessary)
// For example, replace quotes in \`trn-custom-data\` bytes attribute if still required
updatedXmlString = updatedXmlString.replace(
/(<trn-custom-data bytes=")(.\*?)(" \\/>)/g,
(match, p1, p2, p3) => \`${p1}${p2.replace(/"/g, """)}${p3}\`
);
// Import the updated annotation data
await annotManager.importAnnotations(updatedXmlString);
} catch (error) {
return error;
}
It looks like there is an issue regarding copying the exported XFDF data from the console (chrome), and the JSON becomes malformed in the process causing the import issue.
I recommend not altering the XFDF during the import or export:
for import - to keep the measurement captions.
for export - to keep the annotation XFDF data exactly as-is.
If we export the XFDF without modifying it (i.e., without removing the trn-custom-data), the resulting PDF does not display any measurement annotations. However, if we remove the trn-custom-data, the annotations do appear in the PDF, but the measurement units are overlapped at the last drawn measurement index.
Regarding your concern about storing the annotation XFDF string, we are persisting it exactly as received from annotManager.exportAnnotations function, without any transformation or filtering.
We require a definitive solution that ensures:
- The annotations are rendered correctly in the exported PDF.
- The measurement data is preserved accurately without any overlap issues.
- No manual alteration of the XFDF (such as removing trn-custom-data) is necessary.
Please provide guidance on the correct export or processing approach to achieve consistent and accurate annotation rendering.
Using localStorage to export/import the annotation data, I can bring measurement annotations back into the viewer without any issues.
Please see this video for reference, where I use only exportAnnotations & importAnnotations API: Screen Recording 2025-12-10 at 4.31.13 PM.mov