我有一个返回文件流的Web Api函数
[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");
}
}
如何在Jquery Ajax中调用此方法来下载文件,以便弹出保存文件对话框。我正在使用knockout.js,在按钮的单击事件处理程序中,我调用此WebAPI方法并获取流,但我不知道如何将其保存到文件中。
答案 0 :(得分:2)
您无法从ajax调用下载文件。您需要使用get请求下载文件。
您可以使用上面的ajax帖子,但是将文件保存在数据库中,然后返回带有文档ID或URL的json以下载文档。然后,您可以添加将下载文档的隐藏iframe。
请看一下这个答案,该答案说明了如何操作:https://stackoverflow.com/a/16086443/2326610
答案 1 :(得分:1)
AFAIK你无法通过JQuery直接下载文件。解决这个问题的一种方法是在html中声明一个隐藏的iframe:
<iframe id='hiddenIframe' src="" style="display:none; visibility:hidden;" ></iframe>
单击“下载”按钮/链接,然后在jQuery中,您只需设置iframe源:
$('#downloadButton').click(function(){
$('#hiddenIframe').attr('src', 'api/DownloadDocument');
})
答案 2 :(得分:0)
您可以通过修改向webapi发送数据的方式来解决此问题。
在您的Javascript中,您可以创建隐藏的表单并将所需的数据附加到该表单,然后提交。
coffeescript中提供的示例代码,但应易于阅读/转换:
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()
然后我还会创建一个DTO对象,它作为webAPI控制器中的参数,而不是从请求体读取:
public DownloadDocumentDTO
{
public string fileUri {get;set;}
public object otherProp {get;set;}
}
[HttpPost]
public HttpResponseMessage DownloadDocument(DownloadDocumentDTO _dto)
{
....
}
控制器方法中的代码应该没问题。 应该注意的是,如果你试图传递更复杂的数据(不知道你是否做过,因为它没有提到),那么你需要向隐藏表单添加更多输入,它不适用于传递对象起来。