This is a migrated thread and some comments may be shown as answers.

How to set xhr request headers with kendo.saveAs()?

3 Answers 403 Views
Application
This is a migrated thread and some comments may be shown as answers.
Insad
Top achievements
Rank 2
Insad asked on 01 Feb 2017, 10:22 AM

Hello Telerik,

 

I have a problem with the kendo.saveAs() because the server, where the binary files come from, requires an 'Authorization' in the request headers.

I have been looking for an answer but all I found was that the question was asked before, by somebody else, on StackOverflow: http://stackoverflow.com/questions/41406918/kendo-server-export-post-request-headers

But no useful answer was given so i pop the question here because I do need an answer for this :(

 

Best regards,

 

Insad

3 Answers, 1 is accepted

Sort by
0
Boyan Dimitrov
Telerik team
answered on 03 Feb 2017, 08:45 AM

Hello,

Internally the kendo.saveAs methods creates a forma and sends it to the server. I am afraid that it is not really a XMLHttpRequest and so xhr request header is not possible to be set. 

Regards,
Boyan Dimitrov
Telerik by Progress
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
0
Insad
Top achievements
Rank 2
answered on 09 Feb 2017, 10:34 AM
Hello Boyan,

I build a solution for this based on some info found elsewhere on the internet.

I would like to share it with you, so perhaps Telerik might want to use is in some future version ;)

 

//#region -- Download file and save data to a local file --
    // Invoke call to webservice and save file
    // url - Url to get the file from
    // method - GET/POST method
    // defaultFilename - Default filename if none was given from the server
    , saveAs: function (url, method, defaultFilename)
    {
        var caller = this;
 
        Insad.ajaxMaskUI({
            url: url,
            type: method,
            headers: {
                'Authorization': Insad.GetBaseAuthenticationToken()
                // ... Put your headers in here ...
            },
            maskUI: Insad.defaultMaskUI
            , maskPageMsg: 'Downloading file'
        })
        .fail(function (xhr, textStatus, errorThrown) {
            //console.log('error:', textStatus, errorThrown, xhr.getAllResponseHeaders(), xhr);
            var msg = xhr.responseText;
            if (msg === undefined) {
                msg = 'Unknown error';
            }
            console.log('FileDownload failed -> Error handler. Errormessage: ', msg);
            ShowWarning(msg);
 
            caller.handleUIErrorDownload();
        })
        .done(function (data, textStatus, xhr) {
            caller.handleUISuccessDownload(xhr, defaultFilename);
        });
    }
    , handleUIErrorDownload: function ()
    {
        console.log('handleUIError');
        // TODO: Reset stuff / give user more info?
        // ... Put your code in here ...
    }
    , handleUISuccessDownload: function (xhr, defaultFilename)
    {
        console.log('handleUISuccess');
 
        // Save file
        var filename = Insad.GetFilenameFromContent(xhr);
        if (filename === '') {
            filename = defaultFilename;
        }
        Insad.SaveDataToFile(filename, xhr.responseText, xhr.getResponseHeader('Content-Type'));
 
        // TODO: Give user more info?
        // ... Put your code in here ...
    }
//#endregion
 
//#region -- Save data to a local file --
    // Get the filename from the Content-Disposition in the response xhr
    , GetFilenameFromContent: function (xhr)
    {
        var filename = '';
        var disposition = xhr.getResponseHeader('Content-Disposition');
        // Only when inline or attachment are supported at this moment
        if (disposition && (disposition.indexOf('attachment') !== -1 || disposition.indexOf('inline') !== -1)) {
            var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
            var matches = filenameRegex.exec(disposition);
            if (matches != null && matches[1]) {
                filename = matches[1].replace(/['"]/g, '');
            }
        }
        return filename;
    }
 
    // The function that will write the data to a file :)
    , SaveDataToFile: function (filename, data, mimeType)
    {
        var dataFileAsBlob = new Blob([data], {type:mimeType});
        var downloadLink = document.createElement("a");
        downloadLink.download = filename;
        downloadLink.innerHTML = "Download";
        if (window.webkitURL !== null) {                        // Is it Chrome based?
            // Chrome allows the link to be clicked
            // without actually adding it to the DOM.
            downloadLink.href = window.webkitURL.createObjectURL(dataFileAsBlob);
        }
        else {
            // Firefox requires the link to be added to the DOM
            // before it can be clicked.
            downloadLink.href = window.URL.createObjectURL(dataFileAsBlob);
            downloadLink.onclick = destroyClickedElement;       // --> TODO: ?? TEST ?? On Opera use: downloadLink.onclick = document.body.removeChild(event.target);
            downloadLink.style.display = "none";
            document.body.appendChild(downloadLink);
        }
        // Force download
        downloadLink.click();
    }
//#endregion

This is a part from our base library (Insad).

I think you get the idea. If you're missing something I would be happy to provide it to you :)

Instead of calling the 'old' saveAs like:

kendo.saveAs({
    dataURI: url,
    fileName: defaultFilename,
    forceProxy: false
});


You can now use:

Insad.saveAs({
    dataURI: url,
    method: 'GET'// or use 'POST' if you really must ;)
    fileName: defaultFilename
});

I left out the animation part but that shouldn't be to hard I think :)

Best regards,

Albert van Peppen (Insad)

0
Accepted
Boyan Dimitrov
Telerik team
answered on 10 Feb 2017, 02:18 PM

Hello,

Thank you for sharing this solution with our community. I am sure that someone will find it useful. 

Regards,
Boyan Dimitrov
Telerik by Progress
Try our brand new, jQuery-free Angular 2 components built from ground-up which deliver the business app essential building blocks - a grid component, data visualization (charts) and form elements.
Tags
Application
Asked by
Insad
Top achievements
Rank 2
Answers by
Boyan Dimitrov
Telerik team
Insad
Top achievements
Rank 2
Share this question
or