Contents
Introduction
When you use the Ajax call in ASP.NET MVC, you just can return a JSON object but not a file, if you want to do that, you need to create and save the file in server and return it’s path to Ajax, after that, you can call a redirect link for download the file, because this is a temp file, so you should need to delete it after download.
Using the code
The below demo code just for create and download an Excel file:
1. Create an Action for generate the Excel
[HttpPost] public JsonResult ExportExcel() { DataTable dt = DataService.GetData(); var fileName = "Excel_" + DateTime.Now.ToString("yyyyMMddHHmm") + ".xls"; //save the file to server temp folder string fullPath = Path.Combine(Server.MapPath("~/temp"), fileName); using (var exportData = new MemoryStream()) { //I don't show the detail how to create the Excel, this is not the point of this article, //I just use the NPOI for Excel handler Utility.WriteDataTableToExcel(dt, ".xls", exportData); FileStream file = new FileStream(fullPath, FileMode.Create, FileAccess.Write); exportData.WriteTo(file); file.Close(); } var errorMessage = "you can return the errors in here!"; //return the Excel file name return Json(new { fileName = fileName, errorMessage = "" }); }
2. Create the download Action
[HttpGet] [DeleteFileAttribute] //Action Filter, it will auto delete the file after download, I will explain it later public ActionResult Download(string file) { //get the temp folder and file path in server string fullPath = Path.Combine(Server.MapPath("~/temp"), file); //return the file for download, this is an Excel so I set the file content type to "application/vnd.ms-excel" return File(fullPath, "application/vnd.ms-excel", file); }
3. We need to auto delete the file after download, so need to create an Action Filter
public class DeleteFileAttribute : ActionFilterAttribute { public override void OnResultExecuted(ResultExecutedContext filterContext) { filterContext.HttpContext.Response.Flush(); //convert the current filter context to file and get the file path string filePath = (filterContext.Result as FilePathResult).FileName; //delete the file after download System.IO.File.Delete(filePath); } }
4. Use the Ajax call in frontend
//I use blockUI for loading...
.blockUI({ message: '<h3>Please wait a moment...</h3>' });.ajax({
type: "POST",
url: '@Url.Action("ExportExcel","YourController")', //call your conntroller and action
contentType: "application/json; charset=utf-8",
dataType: "json",
}).done(function (data) {
//console.log(data.result);
$.unblockUI();
//get the file name for download
if (data.fileName != "") {
//use window.location.href for redirect to download action for download the file
window.location.href = "@Url.RouteUrl(new { Controller = "YourController", Action = "Download"})/?file=" + data.fileName;
}
});