0

I am trying to download a file from Sharepoing using ajax call from html page. I am able to upload successfully but when I try to download a file, in case of text file, the download is successfull and file opens with correct content, but in case of pdf, the file is downloaded as blank and in case of ppt, the file is corrput.

I am using below code. For now, I am hardcoding everything to get a successfull file. Please let me know what i may be missing.

<apex:page controller="XXX_SharePoint" showHeader="false" sidebar="false"  showChat="false" docType="html-5.0" standardStylesheets="false" action="{!onPageLoad}">
    <script src="https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.1.min.js" type="text/javascript"></script>
    <Script>


        window.onload = () => {
            let code = '{!ACCESS_TOKEN}';   
            let extension = '{!extension}';

            //make a ajax callout
            $.ajax({
                url: "https://m.sharepoint.com/_api/Web/GetFileByServerRelativePath(decodedurl='/XXXDocument/pdf4.pdf')/$value", 
                type: 'get',  
                contentType: true, 
                processData: false, 
                headers: { accept: 'application/json',
                          "Authorization": "Bearer "+code,
                         },
                success: function(response){
                    alert('success response'+response)
                    var a = document.createElement('a');
                    var binaryData = [];
                    binaryData.push(response);
                    var url = window.URL.createObjectURL(new Blob(binaryData),{type: "application/octet-stream"});
                    //var url = window.URL.createObjectURL(response.blob);
                    a.href = url;
                    a.download = 'myfile.pdf';//+extension;
                    document.body.appendChild(a);
                    a.click();
                    a.remove();
                    window.URL.revokeObjectURL(url);
                },
            });
        }
    </Script>

</apex:page>
  • Hi, try adding binaryStringResponseBody: true in your ajax call. – UBK Apr 28 at 12:28
  • I still got the blank pdf. this is how i added - type: 'get', contentType: true, processData: false, binaryStringResponseBody:true, – Samir Apr 28 at 12:45
  • Hi, did you get the file content fine? Problem is when downloading it as a new file, correct? Is opening the URL of the file through SharePoint's download.aspx in a new window an option, like https://<SiteUrl>/_layouts/download.aspx?SourceUrl=https://<SiteUrl>/DocLibrary/Test.docx – UBK Apr 28 at 13:06
  • I am getting the file content but not in readable format. When i download the text file.. it downloads as well as shows the content as well inside it. So I believe the response is correct. All i am missing here is how to parse that response back to pdf – Samir Apr 28 at 13:11
  • Hi, did you try changing the content type to 'application/pdf' already? Looks like you just need to find the proper content type setting for your file. – UBK Apr 28 at 13:18
1

As we have seen in this problem, mentioning responseType :'arraybuffer' or responseType :'blob', or using 'binaryStringResponseBody:true' didn't help.

In all cases we were getting the response but it was not recognized as our intended content type, i.e. PDF. In console it looked like below:

enter image description here

To fix this we have to force the stream to be treated and parsed as 'text/plain', and it worked beautifully!!

window.onload = () => {
        let code = '{!ACCESS_TOKEN}';   

        //make a ajax callout
        $.ajax({
            url: "https://<YourSharePointSite>.sharepoint.com/_api/Web/GetFileByServerRelativePath(decodedurl='/CEPDocument/pdf4.pdf')/$value", 
            type: 'get',  
            contentType: true, 
            processData: false,
            encoding: null,
            headers: { 
                accept: 'application/json',
                "Authorization": "Bearer " + code
                },
            beforeSend: function (request) {
                request.overrideMimeType('text/plain; charset=x-user-defined');
            },
            success: function(response){
                var binary = "";
                var responseTextLen = response.length;

                for ( i = 0; i < responseTextLen; i++ ) {
                    binary += String.fromCharCode(response.charCodeAt(i) & 255)
                }

                var a = document.createElement('a');
                a.href = "data:application/pdf;base64," + btoa(binary);
                a.download = 'myfile.pdf';
                document.body.appendChild(a);
                a.click();
                a.remove();
            },
        });
    }

Here is a different implementation of the 'success' method:

success: function(response){                
                var i = 0,
                dataArray = new Uint8Array(response.length);
                for (; i < response.length; i++) {
                    dataArray[i] = response.charCodeAt(i)
                }

                var blob = new Blob([dataArray.buffer], {
                    type: "application/pdf"
                });
                let link = document.createElement('a');
                link.download = 'ubkfile.pdf';

                let reader = new FileReader();
                reader.readAsDataURL(blob); // converts the blob to base64 and calls onload

                reader.onload = function() {
                  link.href = reader.result;
                  link.click();
                };
            }

Change the content type to "image/png" if you are loading PNG images.

Please mark as answer if it helped you.

| improve this answer | |
  • Thanks a lot. It worked for PDF. Will check for excel and ppt file. – Samir Apr 28 at 18:41
  • I have checked for PDF and PNG. It should work for other file types as well. Just set the file type (MIME type) properly. Check this post for Microsoft Office MIME typeshttps://stackoverflow.com/a/4212908/4489918 – UBK Apr 28 at 20:06
1

Actually, I have discovered that it is really easy to override the underlying XMLHttpRequest that powers the $.ajax() call in order to get an ArrayBuffer response. (See my answer over here.)

What you do is basically something like this:

window.onload = () => {
    let code = '{!ACCESS_TOKEN}';   
    let extension = '{!extension}';

    // make XMLHttpRequest override
    var xhrOverride = new XMLHttpRequest();
    // tell it you want an ArrayBuffer
    xhrOverride.responseType = 'arraybuffer';

    //make a ajax callout
    $.ajax({
        url: "https://m.sharepoint.com/_api/Web/GetFileByServerRelativePath(decodedurl='/XXXDocument/pdf4.pdf')/$value", 
        type: 'GET',  
        contentType: true, 
        processData: false, 
        headers: {
            accept: 'application/json',
            "Authorization": "Bearer "+code,
        },
        xhr: function() { return xhrOverride; },
        success: function(response){

            // "response" is now a proper ArrayBuffer
            // which you can use to make your Blob!

            alert('success response'+response)
            var a = document.createElement('a');
            var binaryData = [];
            binaryData.push(response);
            var url = window.URL.createObjectURL(new Blob(binaryData),{type: "application/octet-stream"});
            //var url = window.URL.createObjectURL(response.blob);
            a.href = url;
            a.download = 'myfile.pdf';//+extension;
            document.body.appendChild(a);
            a.click();
            a.remove();
            window.URL.revokeObjectURL(url);
        },
    });
}
| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.