0

I am using Adobe Embed API (documentation) to embed PDF in web page and allows me to comment, markup, etc. All the files are stored on DigitalOcean Spaces. Issue is that when I modify the PDF then click "Save", it doesn't actually save. Any direction appreciated!

Below is the JS. Here is put the "previewFile" before I register the callback, but didn't work either way (before or after).

document.addEventListener("adobe_dc_view_sdk.ready", function() {
    var adobeDCView = new AdobeDC.View({
         clientId: adobe_key,
         divId: "adobe-dc-view"
    });

    adobeDCView.previewFile({
        content: {
            location: {
                url: document_url
            }
        },
        metaData: {
            fileName: file_name,
            hasReadOnlyAccess: read_only
        }
    });

    adobeDCView.registerCallback(
        AdobeDC.View.Enum.CallbackType.SAVE_API,
        function(metadata, content, options) {
            return new Promise((resolve, reject) => {
                resolve({
                    code: AdobeDC.View.Enum.ApiResponseCode.SUCCESS,
                    data: {
                        metaData: metadata
                    }
                });
            });
        }, saveOptions
    );

    adobeDCView.registerCallback(
        AdobeDC.View.Enum.CallbackType.GET_USER_PROFILE_API,
        function() {
            return new Promise((resolve, reject) => {
                resolve({
                    code: AdobeDC.View.Enum.ApiResponseCode.SUCCESS,
                    data: profile
                });
            });
        },
    );
});  

The simple HTML to render the page.

<!DOCTYPE html>
{% load static %}
<html lang="en">
<head>
    <meta charset="utf-8"/>
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
    <meta id="viewport" name="viewport" content="width=device-width, initial-scale=1"/>

    <link rel="shortcut icon" href="{% static 'assets/images/favicon.png' %}" />
</head>

<body style="margin: 0px">
 <div id="adobe-dc-view"></div>
 <script src="https://documentcloud.adobe.com/view-sdk/viewer.js"></script>
 <script type="text/javascript">
     var document_url = '{{ url }}';
     var file_name = '{{ filename }}';
     var read_only = {{ read_only }};
     var adobe_key = '{{ adobe_embed_key }}';

     const profile = {
         userProfile: {
             name: '{{ user.name }}',
             firstName: '{{ user.fname }}',
             lastName: '{{ user.lname }}',
             email: '{{ user.email }}'
         }
     };

     const saveOptions = {
         autoSaveFrequency: 0,
         enableFocusPolling: false,
         showSaveButton: true
     };
    </script>
    <script type="text/javascript" src="{% static 'assets/js/htw/adobe-embed.js' %}"></script>
</body>
</html>   
joro
  • 11
  • 1
  • I realize I'm not actually doing anything in the "save" callback. How would I save the file at its current location? – joro Aug 06 '22 at 18:28

3 Answers3

1

If anyone has trouble, here as a great example by Joel Geraci that helped. https://codepen.io/practicalPDF/pen/eYBOpEm

const urlToPDF =
   "https://documentcloud.adobe.com/view-sdk-demo/PDFs/Summary.pdf";
const clientId = "e800d12fc12c4d60960778b2bc4370af";
const viewerOptions = {
    embedMode: "FULL_WINDOW",
    defaultViewMode: "FIT_PAGE",
    showDownloadPDF: false,
    showPrintPDF: false,
    showLeftHandPanel: false,
    showAnnotationTools: true
};

const saveOptions = {
    autoSaveFrequency: 0,
    enableFocusPolling: false,
    showSaveButton: true
}

function fetchPDF(urlToPDF) {
    return new Promise((resolve) => {
        fetch(urlToPDF)
            .then((resolve) => resolve.blob())
            .then((blob) => {
                resolve(blob.arrayBuffer());
            })
    })
}

function hideLink() {
    document.getElementById("getFile").style.display = "none";
}

function updateSaveUI(zipFileName) {
    document.getElementById("getFileText").innerHTML = "You can retrieve your saved file from: <a onclick='hideLink(); return true;'' href='https://practicalpdf.com/code-pens/reflect/uploads/" + zipFileName + "'>here.</a>";
    document.getElementById("getFile").style.display = "flex";
}

document.addEventListener("adobe_dc_view_sdk.ready", function () {
    // Create embedded view
    var adobeDCView = new AdobeDC.View({
        clientId: clientId,
        divId: "embeddedView"
    });


adobeDCView.registerCallback(
    AdobeDC.View.Enum.CallbackType.SAVE_API,
    function (metaData, content, options) {
        var uint8Array = new Uint8Array(content);
        var blob = new Blob([uint8Array], { type: 'application/pdf' });
        formData = new FormData();
        var pdfFilename = urlToPDF.split("/").slice(-1)[0];
        pdfFilename = pdfFilename.split(".")[0] + "-" + uuidv4() + ".pdf";
        formData.append('pdfFile', blob, pdfFilename);

        var zipFileName = pdfFilename.replace(".pdf", ".zip");

        fetch("https://practicalpdf.com/code-pens/reflect/", {
            method: 'POST',
            body: formData,
        })
            .then(
                function (response) {
                    if (response.status == 200) {
                        updateSaveUI(zipFileName);
                    }
                }
            )

        return new Promise((resolve, reject) => {
            resolve({
                code: AdobeDC.View.Enum.ApiResponseCode.SUCCESS,
                data: {
                    metaData: { fileName: urlToPDF.split("/").slice(-1)[0] }
                }
            });
        });
    },
    saveOptions
);



    // Show the file
    var previewFilePromise = adobeDCView.previewFile(
        {
            content: { promise: fetchPDF(urlToPDF) },
            metaData: { fileName: urlToPDF.split("/").slice(-1)[0] }
        },
        viewerOptions
    );

});

// Helper Functions:

function uuidv4() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });
}

(function () {
    if (Blob.arrayBuffer != "function") {
        Blob.prototype.arrayBuffer = myArrayBuffer;
    }

    function myArrayBuffer() {
        return new Promise((resolve) => {
            let fileReader = new FileReader();
            fileReader.onload = () => {
                resolve(fileReader.result);
            };
            fileReader.readAsArrayBuffer(this);
        });
    }
})();
joro
  • 11
  • 1
0

What about the c# server end of that upload? Regular file upload code seems to fail with it.

public async Task<IHttpActionResult> ReUploadFIle(int fileId)
    {
        if (!Request.Content.IsMimeMultipartContent())
        {
            return BadRequest("Unsupported media type");
        }
        var fileInfo = client.GetSaifrFilesById(fileId);
        var provider = new MultipartMemoryStreamProvider();
        await Request.Content.ReadAsMultipartAsync(provider);
        var annotatedFolder = ConfigurationManager.AppSettings["annotatedFolder"];
        foreach (var file in provider.Contents)
        {
            var filename = Path.GetFileName(fileInfo.annotatedFile).Split('.')[0] + DateTime.Now.ToString("mmddyyyyhhmmss") +"."+ Path.GetFileName(fileInfo.annotatedFile).Split('.')[1];
            byte[] bytes = Convert.FromBase64String(file.);
            var serverPath = Path.Combine(annotatedFolder, filename);
            File.WriteAllBytes(serverPath, buffer);
        }
        return Ok();
    }
Cin0s3
  • 1
0

To be clear, saving from Embed will, by default, save to your machine. If you want it to save to a server, you need to handle the save event, and write server-side code to get the data and overwrite the copy there. You would want to be very careful here to ensure this is done in a secure manner.

Raymond Camden
  • 10,661
  • 3
  • 34
  • 68