使用Jquery Post的Web API下载文件

本文关键字:API 下载 文件 Web Jquery Post 使用 | 更新日期: 2023-09-27 18:08:15

我有一个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方法并获得流,但我不知道如何将其保存到文件中。

使用Jquery Post的Web API下载文件

不能从ajax调用中下载文件。您将需要使用get请求来下载文件。

你可以做的是使用你的ajax post如上所述,但将文件保存在数据库中,然后返回json与文档的id或url下载文档。然后你可以添加一个隐藏的iframe来下载文档。

看看这个答案,它展示了如何做到这一点:https://stackoverflow.com/a/16086443/2326610

恐怕你不能直接通过JQuery下载文件。解决这个问题的一个方法是在html:

中声明一个隐藏iframe。
<iframe id='hiddenIframe' src="" style="display:none; visibility:hidden;" ></iframe>

当你点击下载按钮/链接,然后在jQuery中,你可以简单地设置iframe源:

$('#downloadButton').click(function(){
    $('#hiddenIframe').attr('src', 'api/DownloadDocument');
})

你可以通过修改你向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)
{
    ....
}

控制器方法中的代码应该是正确的。应该注意的是,如果你试图传递更复杂的数据(不知道你是否这样做,因为它没有提到),那么你将需要添加更多的输入到隐藏表单,它将无法传递对象。