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