如何使用 jQuery Ajax 调用从 ASP.NET Web Api 下载 CSV 文件
Posted
技术标签:
【中文标题】如何使用 jQuery Ajax 调用从 ASP.NET Web Api 下载 CSV 文件【英文标题】:How to download CSV file from ASP.NET Web Api using jQuery Ajax call 【发布时间】:2013-02-26 08:56:06 【问题描述】:我正在研究如何通过 jQuery ajax 调用从 ASP.NET Web Api 下载 CSV 文件。 CSV 文件是基于自定义 CsvFormatter 从 Web API 服务器动态生成的。
来自 jQuery 的 Ajax:
$.ajax(
type: "GET",
headers:
Accept: "text/csv; charset=utf-8",
,
url: "/api/employees",
success: function (data)
);
在服务器上,EmployeeCsvFormatter
的实现与以下文章类似,源自BufferedMediaTypeFormatter
:
http://www.asp.net/web-api/overview/formats-and-model-binding/media-formatters
public class EmployeeCsvFormatter : BufferedMediaTypeFormatter
public EmployeeCsvFormatter()
SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/csv"));
...
我还添加了覆盖方法来表示我想像正常下载文件一样下载(可以在下载选项卡中查看下载文件):
public override void SetDefaultContentHeaders(Type type,
HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
base.SetDefaultContentHeaders(type, headers, mediaType);
headers.Add("Content-Disposition", "attachment; filename=yourname.csv");
headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
但它不起作用,下载文件没有显示在状态栏或 Chrome 的下载选项卡中,即使来自 Fiddler,我看到它的响应似乎是正确的:
HTTP/1.1 200 OK
Server: ASP.NET Development Server/11.0.0.0
Date: Mon, 11 Mar 2013 08:19:35 GMT
X-AspNet-Version: 4.0.30319
Content-Disposition: attachment; filename=yourname.csv
Cache-Control: no-cache
Pragma: no-cache
Expires: -1
Content-Type: application/octet-stream
Content-Length: 26
Connection: Close
1,Cuong,123
1,Trung,123
我的 ApiController 方法:
public EmployeeDto[] Get()
var result = new[]
new EmployeeDto() Id = 1, Name = "Cuong", Address = "123",
new EmployeeDto() Id = 1, Name = "Trung", Address = "123",
;
return result;
它一定是我没有弄清楚的地方出错了。如何像正常方式一样通过下载 CSV 文件使其工作?
【问题讨论】:
无法使用 AJAX 下载到文件。只需将用户重定向到 urlwindow.location=url
,如果服务器强制下载他们不会离开当前页面
@charlietfl: 我怎样才能用这种方式设置 Accept 标头?
您对accept header
有什么期望?不能通过下载强制用户接受任何内容
【参考方案1】:
jQuery Plugin for Requesting Ajax-like File Downloads 在没有 Ajax 的情况下可以做到 using a simple form submit。
内部:
jQuery('<form action="'+ url +'" method="'+ (method||'post') +'">'+inputs+'</form>')
.appendTo('body').submit().remove()
它有一个 ajax 风格的界面,所以你可以从外面这样调用它
$.download('/api/employees','format=csv');
另一种简单的方法使用:
$('#btnDownload').click(function (e)
e.preventDefault();
window.location = "/api/employees?format=csv";
);
在服务器上,MediaTypeMappings
必须通过添加一个构造函数来使用:
public EmployeeCsvFormatter(MediaTypeMapping mediaTypeMapping)
: this()
MediaTypeMappings.Add(mediaTypeMapping);
然后,将此格式化程序添加到 Web Api 配置中:
configuration.Formatters.Add(new EmployeeCsvFormatter
(new QueryStringMapping("format", "csv", "text/csv")));
【讨论】:
这种方式如何添加Accept header? 好点。我担心浏览器会添加一个。您可以将格式放在 URL 中,例如$.download('/api/employees/csv','');
或作为参数:$.download('/api/employees/','format=csv');
啊,开箱即用?有时候,生活并不像恐惧那么复杂!将更新答案。
哦,我傻了,现在我读到 queryStringMapper 是必需的。请使用适当的映射器进行更新。
如果 Get() 或 Post() 接受参数,你将如何使用 jquery 下载来适应?【参考方案2】:
作为一种替代方法,可以通过单击锚点 () 或按钮提供下载,并将请求的 URL 设置为响应附件的 API 方法。
在CsvMediaTypeFormatter
(Derived from System.Net.Http.Formatting.MediaTypeFormatter)中,除了如上面的答案所示映射text/csv MIME类型外,我发现还需要做以下工作:
public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType)
base.SetDefaultContentHeaders(type, headers, mediaType);
headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
FileName = string.Concat("data", DateTime.UtcNow.ToString("yyyyMMddhhmmss"), ".csv")
;
headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
注意:写流时,设置Content-Length
标头,记得刷新流。我发现如果不调用Flush()
,即使设置了正确的内容长度,返回的响应也不会成功返回客户端。
【讨论】:
【参考方案3】:也可以在beforeSend中通过修改xhr来设置请求头。
$.ajax(
url: "/api/employees",
type: "GET",
beforeSend: function (xhr)
xhr.setRequestHeader("Accept", "text/csv");
,
success: function (data)
);
【讨论】:
以上是关于如何使用 jQuery Ajax 调用从 ASP.NET Web Api 下载 CSV 文件的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 jQuery AJAX 调用 ASP.Net 字符串函数?
如何从 jQuery ajax 调用将复杂对象传递给 ASP.NET WebApi GET?
使用 jquery ajax 从 asp.net 网页表单页面调用 web api url
如何使用 ASP.NET MVC Rest API 调用和 jQuery Ajax 下载文件