(此文章同時發表在本人微信公眾號“dotNET每日精華文章”,歡迎右邊二維碼來關注。)
題記:在ASP.NET 5(MVC 6)中處理上傳文件的方式和之前有所不同。
在MVC 5之前的版本中上傳文件,有兩種方式。
1,直接對Request.Files進行訪問獲取HttpPostedFileBase,如下面代碼所示:
[HttpPost] public ActionResult Upload() { string path = @"D:\Temp\"; HttpPostedFileBase photo = Request.Files["photo"]; if(photo != null) photo.SaveAs(path + photo.FileName); return RedirectToAction("Index"); }
2,通過模型綁定獲取HttpPostedFileBase,如下面代碼所示:
[HttpPost] public ActionResult Upload(HttpPostedFileBase photo) { string path = @"D:\Temp\"; if(photo != null) photo.SaveAs(path + photo.FileName); return RedirectToAction("Index"); }
更多詳細的用法可以參考CodeProject的這篇文章《Uploading and returning files in ASP.NET MVC》。
在MVC 6中同樣也是有兩種方式,只是提供的類和之前有所不同,沒有HttpPostedFileBase,取而代之的是IFormFile,且額外的一些文件信息放到了ContentDispositionHeaderValue。
1,直接使用Request.Form.Files訪問IFormFile,如下代碼所示:
[HttpPost] public ActionResult Upload() { string path = @"D:\Temp\"; IFormFile photo = Request.Form.Files["photo"]; if (photo != null) { var parsedContentDisposition = ContentDispositionHeaderValue.Parse(photo.ContentDisposition); var originalName = parsedContentDisposition.FileName.Replace("\"", ""); photo.SaveAs(path + originalName); } return RedirectToAction("Index"); }
大家可以注意到了,我對parsedContentDisposition.FileName進行了一個替換處理。這是因為FileName這個屬性值會帶有前后雙引號。我不知道這個是個bug還是故意設計,過一會去提個Issue問問。
2,通過模型綁定獲取IFormFile,如下面代碼所示:
[HttpPost] public ActionResult Upload(IFormFile photo) { string path = @"D:\Temp\"; if (photo != null) { var parsedContentDisposition = ContentDispositionHeaderValue.Parse(photo.ContentDisposition); var originalName = parsedContentDisposition.FileName.Replace("\"", ""); photo.SaveAs(path + originalName); } return RedirectToAction("Index"); }
另外,還需要注意的是,在MVC 6中已經無法用Server.MapPath這樣的方法來得到虛擬地址對應的物理地址了,只能通過IHostingEnvironment.MapPath來獲取(此方法是一個擴展方法)。而要使用IHostingEnvironment的實例,必須把其注入到Controller中(IHostingEnvironment是默認被系統注冊的,無需也無法顯式注冊)。經過我的試驗,只能通過構造器注入,而無法通過[Activate]來屬性注入。