Вопрос

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>
Это было полезно?

Решение

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.

Другие советы

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);
        },
    });
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с sharepoint.stackexchange
scroll top