Reputation: 33
I have a web Api function that returns a file stream
[HttpPost]
public HttpResponseMessage DownloadDocument([FromBody] parameters)
{
try
{
var stream = FileHelper.GetFilesStream(fileUrl);
HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(stream) };
result.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
result.Content.Headers.ContentDisposition.FileName = fileName;
return result;
}
catch (Exception)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, "File Not Found");
}
}
How can I call this method in Jquery Ajax to download the file so the save file dialog pops up. I am working with knockout.js, in click event handler of a button, I call this WebAPI method and I get the stream, but I don't know how to save it to the file.
Upvotes: 2
Views: 10534
Reputation: 7958
You cannot download a file from an ajax call. You will need to use a get request to download a file.
What you could do is use your ajax post as above but save the file in a db and then return json with the id of the document or a url to download the document. You can then add a hidden iframe which will download the document.
Have a look at this answer which shows how to do it: https://stackoverflow.com/a/16086443/2326610
Upvotes: 2
Reputation: 5053
You can get around this by modifying how you are sending data to your webapi.
In your Javascript you can create a hidden form and append the data that you need to that, and then submit it.
Sample code presented in coffeescript, but should be easily read/converted:
downloadDocument: (fileUri, otherProp, successCallback) =>
if $('#hidden-form').length > 0
$('#hidden-form').remove()
$('<form>').attr(
method: 'POST',
id: 'hidden-form',
action: '/your/url/to/method'
).appendTo('body');
$('<input>').attr({
type: 'hidden',
id: 'fileUri',
name: 'fileUri',
value: fileUri
}).appendTo('#hidden-form')
$('<input>').attr({
type: 'hidden',
id: 'otherProp',
name: 'otherProp',
value: otherProp
}).appendTo('#hidden-form')
$('#hidden-form').bind("submit", successCallback)
$('#hidden-form').submit()
I would then also create a DTO object which is taken in as a parameter in your webAPI controller, rather than reading from the request body:
public DownloadDocumentDTO
{
public string fileUri {get;set;}
public object otherProp {get;set;}
}
[HttpPost]
public HttpResponseMessage DownloadDocument(DownloadDocumentDTO _dto)
{
....
}
The code in your controller method should be alright. It should be noted that if you are trying to pass up more complex data (don't know if you do since its not mentioned), then you will need to add more input to the hidden form, it won't work for passing object up.
Upvotes: 0
Reputation: 2261
AFAIK you cannot directly download files via JQuery. One way around this is to declare a hidden iframe in html:
<iframe id='hiddenIframe' src="" style="display:none; visibility:hidden;" ></iframe>
When you click the Download button/link, then in jQuery, you can simply set the iframe source by doing:
$('#downloadButton').click(function(){
$('#hiddenIframe').attr('src', 'api/DownloadDocument');
})
Upvotes: 1