大家都應該知道,在ASP.NET MVC裡,如果通過Ajax調用後臺控制器時,可以返回一個JSON對象,但並不能直接返迴文件(除非重新整理頁面,那就不是Ajax啦),所以如果想用Ajax組建檔案並下載的話,那隻要將產生的檔案先儲存到服務器上,然後再將檔案路徑通過JSON返回,之後才可以進行下載,當然由於是暫時性存放,所以當下載完後就需要馬上刪除相應的檔案。
以下是做法以動態產生Excel為例(產生Excel的具體步驟我就省略了,這並不是此文章的重點):
1. 首先創建Action產生Excel檔案
[HttpPost]public JsonResult ExportExcel(){ DataTable dt = DataService.GetData(); var fileName = "Excel_" + DateTime.Now.ToString("yyyyMMddHHmm") + ".xls"; //將產生的檔案儲存到服務器的臨時目錄裡 string fullPath = Path.Combine(Server.MapPath("~/temp"), fileName); using (var exportData = new MemoryStream()) { //如何產生Excel這裡就不詳細說明啦,我這裡對Excel的操作使用的是 NPOI 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 Json(new { fileName = fileName, errorMessage = "" });}
2. 創建下載用的 Action
[HttpGet][DeleteFileAttribute] //Action Filter, 下載完後自動刪除檔案,這個屬性稍後解釋public ActionResult Download(string file){ //到服務器臨時檔案目錄下載相應的檔案 string fullPath = Path.Combine(Server.MapPath("~/temp"), file); //返迴文件對象,這裡用的是Excel,所以檔案頭使用了 "application/vnd.ms-excel" return File(fullPath, "application/vnd.ms-excel", file);}
3. 由於要做到下載完後自動刪除檔案,所以再創建一個 Action Filter
public class DeleteFileAttribute : ActionFilterAttribute{ public override void OnResultExecuted(ResultExecutedContext filterContext) { filterContext.HttpContext.Response.Flush(); //將當前filter context轉換成具體操作的檔案並獲取檔案路徑 string filePath = (filterContext.Result as FilePathResult).FileName; //有檔案路徑後就可以直接刪除相關檔案了 System.IO.File.Delete(filePath); }}
4. 最後在前臺添加 Ajax 調用的代碼:
//這裡我使用了 blockUI 做loading...$.blockUI({ message: '<h3>Please wait a moment...</h3>' }); $.ajax({ type: "POST", url: '@Url.Action("ExportExcel","YourController")', //調用相應的controller/action contentType: "application/json; charset=utf-8", dataType: "json",}).done(function (data) { //console.log(data.result); $.unblockUI(); //接收返回的檔案路徑,此檔案這時已儲存到服務器上了 if (data.fileName != "") { //通過調用 window.location.href 直接跳轉到下載 action 進行檔案下載操作 window.location.href = "@Url.RouteUrl(new { Controller = "YourController", Action = "Download"})/?file=" + data.fileName; }});