Here is a solution to get download links to notes attachment in dynamics 365
Create a new web resource called Download.html with the following code
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8" />
<title></title>
<script src="/WebResources/jquery3.6.js" type="text/javascript"></script>
<script src="/WebResources/ClientGlobalContext.js.aspx" type="text/javascript"></script>
</head>
<body>
<script type="module">
async function DownloadFile() {
console.log("Downloading file..")
let urlParams = new URLSearchParams(window.top.location.search);
if (urlParams.has("data")) {
let annotId = urlParams.get("data");
console.log("Note ID : ", annotId);
let openOptions = { openMode: 2 };
let fileOptions = {};
try {
let r = await (await fetch(`/api/data/v9.2/annotations(${annotId})?$select=documentbody,filename,mimetype,filesize`)).json();
fileOptions = {
fileContent: r.documentbody,
fileName: r.filename,
mimeType: r.mimetype,
fileSize: r.filesize
};
console.log(r);
}
catch (ex1) {
await window.top.Xrm.Navigation.openErrorDialog({ message: "File Not Found!" });
window.top.close();
}
try {
await window.top.Xrm.Navigation.openFile(fileOptions, openOptions);
console.log("File downloaded successfully");
}
catch (ex2) {
window.top.Xrm.Navigation.openErrorDialog({ message: "Error downloading file, please contact the Attachment owner" });
}
}
else {
window.top.close();
}
}
$(document).ready(async function () {
await DownloadFile();
});
</script>
</body>
</html>
Now to generate direct download links to a note attachment from say another web resource or external application simply call the above resource with the annotation/note id as follows
<a href="https://{orgname}.crm.dynamics.com/WebResources/{publishername}_Download.html?data={ANNOTATIONID}">Download File</>
Replace values in the above anchor link as needed.