Copy link to clipboard
Copied
First Scenario:
1. We open a pdf(with acro fields) on the PDF Embed Viewer,
2. Add some annotations using the UI.
3. We saved the annotations on our database as a json format.
4. If we open again this document we load the annotations from the database using annotationManager api
5. Everything works fine.
Second Scenario:
1. We opened the same pdf on Scenario 1
2. Fill some data on some fields (or trigger some ui functions to update the pdf content)
3. Saved the pdf
4. Reopen the PDF
5. Annotations are not loaded , we are getting errors "Invalid value of Annotations" and "Annotation not found for given id".
1 Correct answer
Could you check the file ID of Document B (specified in the metadata field and passed to adobeDCView.previewFile)?
The error in the screenshot "Invalid value of Annotations ["Annotation <id> is not having valid source."]" is shown when the source mentioned in the annotation JSON does not match the file ID.
Copy link to clipboard
Copied
Hi!
Please share the snippet of your code so we can debug the issue. You could also share the link to the webpage if it's publicly accessible.
Thanks.
Copy link to clipboard
Copied
Please clarify. In scenario 2, how are you saving the PDF? What do you mean by "reopen" in step 4?
Copy link to clipboard
Copied
We saved the pdf into our database (SQL Server). Here is the javascript code for our viewer.
document.addEventListener("adobe_dc_view_sdk.ready", function () {
var fileUrl = pdfInfo.url;
if (/^(http|https)/i.test(pdfInfo.url)) {
//we need to get the file from this domain thru our proxy endpoint to avoid CORS issues
fileUrl = '/pdf/stream?file=' + encodeURIComponent(pdfInfo.url);
}
var adobeDCView = new AdobeDC.View({ clientId: pdfInfo.adobeClientId, divId: "adobe-dc-view" });
var previewFilePromise = adobeDCView.previewFile({
content: {
location: { url: fileUrl }
},
metaData: {
fileName: pdfInfo.name || "file.pdf",
id: pdfInfo.id || "file1" /* this is required for annotation to work */
}
}, {
enableAnnotationAPIs: true,
});
previewFilePromise.then(adobeViewer => {
adobeViewer.getAnnotationManager().then(annotationManager => {
window.AdobeAnnotationManager = annotationManager;
// All annotation APIs can be invoked here
console.log("loading annotations ....")
return loadDocumentAnnotations(pdfInfo.url).then(function (listOfAnnotations) {
console.log("List of annotations from db ", listOfAnnotations);
if (listOfAnnotations && listOfAnnotations.length) {
annotationManager.addAnnotations(listOfAnnotations).then(function () {
registerAnnotationEventListeners(annotationManager);
});
} else {
registerAnnotationEventListeners(annotationManager);
}
document.title = pdfInfo.name;
var div = document.querySelector("#righPanel");
if (div) {
div.classList.remove("loading");
}
toggleRightPanel();
var note = window.pdfInfo.note;
if (note) {
annotationManager.selectAnnotation(note);
}
}).catch(function(){
registerAnnotationEventListeners(annotationManager);
});
});
adobeViewer.getAPIs().then(function (apis) {
if (window.pdfInfo.page) {
var x = Number(pdfInfo.x || 0);
var y = Number(pdfInfo.y || 0);
var page = Number(page) || 1;
setTimeout(function () {
apis.gotoLocation(page, x, y);
}, 800);
}
window.AdobeVieweApi = apis;
});
window.AdobeViewer = adobeViewer;
});
adobeDCView.registerCallback(AdobeDC.View.Enum.CallbackType.GET_USER_PROFILE_API, function () {
return Promise.resolve({
code: AdobeDC.View.Enum.ApiResponseCode.SUCCESS,
data: {
userProfile: {
name: window.pdfInfo.username,
firstName: "",
lastName: "",
email: window.pdfInfo.username
}
}
});
});
adobeDCView.registerCallback(
AdobeDC.View.Enum.CallbackType.SAVE_API,
function (metaData, content, options) {
return new Promise(function (resolve, reject) {
var url = '/pdf/updatebinary?fileStreamId=' + pdfInfo.documentId;
console.log("saving...")
fetch(url, {
method: 'POST',
body: content
}).then(function (response) {
return response.json();
}).then(function (result) {
console.log("saving done");
resolve({
code: AdobeDC.View.Enum.ApiResponseCode.SUCCESS,
data: {
metaData: metaData
}
});
}).catch(function (err) {
reject({
code: AdobeDC.View.Enum.ApiResponseCode.FAIL,
data: {
metaData: metaData
}
});
});
});
}, {
autoSaveFrequency: 0,
enableFocusPolling: false,
showSaveButton: true
}
);
adobeDCView.registerCallback(
AdobeDC.View.Enum.CallbackType.EVENT_LISTENER,
function (event) {
console.log("Alert annotation started.......................")
console.log(event.type, event.data);
toggleRightPanel('notes');
}, {
// Pass the events to receive.
// If no event is passed in listenOn, then all the annotation events will be received.
listenOn: [
AdobeDC.View.Enum.AnnotationEvents.ANNOTATION_ADDED,
AdobeDC.View.Enum.AnnotationEvents.ANNOTATION_CLICKED,
AdobeDC.View.Enum.AnnotationEvents.ANNOTATION_MODE_STARTED
],
enableAnnotationEvents: true
}
);
adobeDCView.registerCallback(
AdobeDC.View.Enum.CallbackType.EVENT_LISTENER,
function (event) {
console.log("preview selection end fired")
AdobeVieweApi.getSelectedContent().then(function (result) {
copyToClipboard(result);
});
}, {
listenOn: [AdobeDC.View.Enum.FilePreviewEvents.PREVIEW_SELECTION_END],
enableFilePreviewEvents: true
}
);
adobeDCView.registerCallback(
AdobeDC.View.Enum.CallbackType.EVENT_LISTENER,
function (event) {
console.log("event", event);
var copiedText = event.data.copiedText;
var frame = document.querySelector('#propIFrame');
if (frame && frame.contentWindow) {
var selectedField = frame.contentWindow.lastFocusedField;
if (selectedField && /(input|select|textarea)/i.test(selectedField.nodeName)) {
selectedField.value = copiedText;
}
}
}, {
//Pass the PDF analytics events to receive.
//If no event is passed in listenOn, then all PDF analytics events will be received.
listenOn: [AdobeDC.View.Enum.PDFAnalyticsEvents.TEXT_COPY],
enablePDFAnalytics: true
}
);
});
Copy link to clipboard
Copied
function loadDocumentAnnotations(file) {
return fetch('/pdf/GetNotes?file=' + encodeURIComponent(file), {
method: 'GET',
}).then(function (response) {
return response.json();
}).then(function (result) {
return JSON.parse(result.ResultString || []);
})
}
function saveDocumentAnnotations(fileName, fileUrl, annotationData) {
var payload = new FormData();
payload.append("name", fileName);
payload.append("file", fileUrl);
payload.append("notes", JSON.stringify(annotationData))
return fetch('/pdf/SaveNotes', {
method: 'POST',
body: payload
}).then(function (response) {
return response.json();
}).then(function (result) {
return result;
});
}
function registerAnnotationEventListeners(annotationManager) {
var eventOptions = {
// Pass the events to receive.
// If no event is passed in listenOn, then all the annotation events will be received.
listenOn: [
"ANNOTATION_ADDED", "ANNOTATION_UPDATED", "ANNOTATION_DELETED"
]
};
annotationManager.registerEventListener(
function (event) {
console.log(event.type, event.data);
annotationManager.getAnnotations().then(function (result) {
console.log("all annotations => ", result);
console.log("saving annotations");
saveDocumentAnnotations(pdfInfo.name, pdfInfo.url, result).then(function (done) {
console.log("Annotations updated.")
});
});
},
eventOptions
);
}
function toggleRightPanel(panel) {
panel = panel || sessionStorage.getItem("rpanel") || "notes";
document.body.setAttribute('data-rpanel', panel);
sessionStorage.setItem("rpanel", panel);
//AdobeViewer.executeCommand('TOGGLE_COMMENTING', true);
AdobeAnnotationManager.setConfig({ showCommentsPanel: true });
}
function copyToClipboard(str) {
var el = document.createElement('textarea');
el.value = str;
el.setAttribute('readonly', '');
el.style.position = 'absolute';
el.style.left = '-9999px';
document.body.appendChild(el);
var selected = document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false;
el.select();
document.execCommand('copy');
document.body.removeChild(el);
if (selected) {
document.getSelection().removeAllRanges();
document.getSelection().addRange(selected);
}
};
Copy link to clipboard
Copied
I'm wondering where is the window.pdfInfo from in above code?
Copy link to clipboard
Copied
We re-open the pdf by reloading the our viewer url or opening another browser window.
Copy link to clipboard
Copied
When the pdf is edited, we have an option to create a new version of the pdf on our UI. If new version option is selected we will create a new pdf document and we created a copy of the annotations from the original pdf to the new version.
When we open the new pdf version we then load the copied annotations but it is failing and we get the above errors.
Copy link to clipboard
Copied
Quick Question:
If I created annotations on Document A and saved the annotations to the database, can I apply that annotations to Document B?
Document A and Document B may differ on the Acrofields Values.
Document A and Document B may also differ on some text contents but they will have the same Number of pages, Page Sizes/Dimensions.
Copy link to clipboard
Copied
Could you check the file ID of Document B (specified in the metadata field and passed to adobeDCView.previewFile)?
The error in the screenshot "Invalid value of Annotations ["Annotation <id> is not having valid source."]" is shown when the source mentioned in the annotation JSON does not match the file ID.
Copy link to clipboard
Copied
Thank you, this solves the problem.
Copy link to clipboard
Copied
i am able to save annotations to json file, but unable to retrive from json file, plesae help with server side GetNotes.
i am using php for saving and reading json file
function loadDocumentAnnotations(file) {
return fetch('read.php?file=' + encodeURIComponent(file), {
method: 'GET',
}).then(function (response) {
console.log(response);
return response.json();
}).then(function (result) {
console.log(result);
return JSON.parse(result.ResultString || []);
})
}
function saveDocumentAnnotations(fileName, fileUrl, annotationData) {
var payload = new FormData();
payload.append("name", fileName);
payload.append("file", fileUrl);
payload.append("notes", JSON.stringify(annotationData))
return fetch('save.php', {
method: 'POST',
body: payload
}).then(function (response) {
console.log(response);
return response.json();
}).then(function (result) {
console.log(result);
return result;
});
save.php
<?php
// check if a form was submitted
if( !empty( $_POST ) ){
// convert form data to json format
$json = json_encode( $_POST );
// make sure there were no problems
//if( json_last_error() != JSON_ERROR_NONE ){
//exit; // do your error handling here instead of exiting
// }
$file = 'entries.json';
// write to file
// note: _server_ path, NOT "web address (url)"!
file_put_contents( $file, $json);
}
read.php
header('Content-Type: application/json');
$obj = json_decode($jsonobj);
echo json_encode($obj->{'notes'});

