您无法直接通过AJAX调用返回文件进行下载,因此另一种方法是使用AJAX调用将相关数据发布到服务器。然后,您可以使用服务器端代码创建Excel文件(我建议使用EPPlus或NPOI,尽管听起来您已经掌握了这部分内容)。
更新于2016年9月:
我的原始答案(下面)已经有3年多了,所以我认为我应该更新一下,因为当通过AJAX下载文件时不再在服务器上创建文件,但是我保留了原始答案,因为根据您的具体要求可能仍然有用。
我的MVC应用程序中常见的场景是通过具有某些用户配置的报告参数(日期范围、过滤器等)的Web页面进行报告。当用户指定参数时,将它们发布到服务器,生成报告(例如,将Excel文件作为输出),然后将结果文件存储为字节数组在TempData桶中,并具有唯一的引用。将此引用作为Json结果传回到我的AJAX函数,随后重定向到单独的控制器操作,以从TempData中提取数据并下载到最终用户的浏览器。
为了更详细地说明,假设您有一个MVC视图,其中有一个绑定到模型类的表单,让我们称之为模型
ReportVM
。
首先,需要一个控制器操作来接收提交的模型,例如:
public ActionResult PostReportPartial(ReportVM model){
ExcelPackage workbook = new ExcelPackage();
string handle = Guid.NewGuid().ToString();
using(MemoryStream memoryStream = new MemoryStream()){
workbook.SaveAs(memoryStream);
memoryStream.Position = 0;
TempData[handle] = memoryStream.ToArray();
}
return new JsonResult() {
Data = new { FileGuid = handle, FileName = "TestReportOutput.xlsx" }
};
}
这里是一个将我的MVC表单提交给上述控制器并接收响应的AJAX调用示例:
$ajax({
cache: false,
url: '/Report/PostReportPartial',
data: _form.serialize(),
success: function (data){
var response = JSON.parse(data);
window.location = '/Report/Download?fileGuid=' + response.FileGuid
+ '&filename=' + response.FileName;
}
})
控制器操作以处理文件下载:
[HttpGet]
public virtual ActionResult Download(string fileGuid, string fileName)
{
if(TempData[fileGuid] != null){
byte[] data = TempData[fileGuid] as byte[];
return File(data, "application/vnd.ms-excel", fileName);
}
else{
return new EmptyResult();
}
}
如果需要,可以很容易地进行其他更改,将文件的MIME类型作为第三个参数传递,以便一个控制器操作可以正确地提供各种输出文件格式。
这样就可以避免在服务器上创建和存储任何物理文件,因此不需要任何清理例程,对最终用户来说也是无缝的。
请注意,使用TempData
而不是Session
的优点在于,一旦读取TempData
,数据就会被清除,因此如果您有大量文件请求,则在内存使用方面更有效率。请参见TempData Best Practice。
原始答案
您无法通过AJAX调用直接返回要下载的文件,因此,另一种方法是使用AJAX调用将相关数据发布到服务器。然后,您可以使用服务器端代码创建Excel文件(我建议使用EPPlus或NPOI进行此操作,尽管听起来好像您已经完成了此部分)。
一旦服务器上创建了文件,请将文件路径(或仅文件名)作为返回值传递回您的AJAX调用,然后设置JavaScript
window.location 到此URL,这将提示浏览器下载文件。从最终用户的角度来看,文件下载操作是无缝的,因为他们从未离开发出请求的页面。以下是一个简单的编写示例以实现此目的的AJAX调用:
$.ajax({
type: 'POST',
url: '/Reports/ExportMyData',
data: '{ "dataprop1": "test", "dataprop2" : "test2" }',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (returnValue) {
window.location = '/Reports/Download?file=' + returnValue;
}
});
- url参数是您的代码将创建Excel文件的控制器/操作方法。
- data参数包含从表单中提取的json数据。
- returnValue将是您新创建的Excel文件的文件名。
- window.location命令重定向到实际返回文件以供下载的控制器/操作方法。
下载操作的示例控制器方法如下:
[HttpGet]
public virtual ActionResult Download(string file)
{
string fullPath = Path.Combine(Server.MapPath("~/MyFiles"), file);
return File(fullPath, "application/vnd.ms-excel", file);
}