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
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
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(); }//#endregionThis 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)
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