2013年6月3日 星期一

[Asp.net MVC] FileResult

在ASP.NET MVC 中,若要實現檔案文件等的上下傳,最簡單的就是使用FileResult。

FileResult 是基於檔案文件的一個ActionResult實作,目前在ASP.NET MVC 中定義了如下三個FileResult的實作 :

  • FileContentResult: Sends the contents of a binary file to the response.
protected virtual FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName);
  • FilePathResult: Sends the contents of a file to the response
protected virtual FilePathResult File(string fileName, string contentType, string fileDownloadName);
  • FileStreamResult: Sends binary content to the response by using a Stream instance
protected virtual FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName);

實作範例 

1.FileContentResult

        public FileContentResult fileContextResult(int productId = 2)
        {
            var prod = db.Products.FirstOrDefault(q => q.ProductID == productId);
            return prod != null ? File(prod.ImageData, prod.ImageMimeType) : null;
        }
2.FilePathResult
        public FilePathResult filePathResult()
        {
            ViewBag.Status = "FilePathResult";
            string path = Server.MapPath("/Content/Guns/2.png");
            return File(path, "image/png", "02.png");
        }
3.FileStreamResult
        public FileStreamResult fileStreamResult()
        {
            string path = Server.MapPath("/Content/Guns/2.png");
            var image = new Bitmap(path);            
            MemoryStream  stream = new MemoryStream();
            image.Save(stream, ImageFormat.Jpeg);
            stream.Seek(0, SeekOrigin.Begin);
            return File(stream, "image/jpeg");
        }

View

@ViewBag.Status

@Html.ActionLink("Download", "filePathResult")

上傳實作

Action :
        [HttpPost]
        public ActionResult Edit(Product product, HttpPostedFileBase image)
        {
        // 注意這邊須使用 HttpPostedFileBase 來接 multipart/form-data 格式的資料
            if (ModelState.IsValid)
            {
                if (image != null)
                {
                    product.ImageMimeType = image.ContentType;
                    product.ImageData = new byte[image.ContentLength];
                    image.InputStream.Read(product.ImageData, 0, image.ContentLength);
                }

                db.SaveProduct(product);
                TempData["message"] = string.Format("{0} has been saved", product.Name);
                return RedirectToAction("Index");
            }
            return View(product);
        }

View :
@using (Html.BeginForm("Edit", "Admin", FormMethod.Post, new { enctype= "multipart/form-data" }))
{
    
    @Html.EditorForModel();
    
    
Image
@if (Model.ImageData == null) { placehold } else { }
Upload new File
@Html.ActionLink("Cancel", "Index") }

這邊的重點在於
Html.BeginForm("Edit", "Admin", FormMethod.Post, new { enctype= "multipart/form-data" })

必須先將 Form 宣告成 multipart,代表此「表單」包含多重欄位。詳細說明請參閱RFC 2388 。

PS:另外若非不得已請儘量避免在View中出現商業邏輯,如上方的  if   else ,這邊僅是方便文章作呈現。

參考資訊
蒋金楠(Artech)的博客
RFC 2388
mime-types-full
石頭閒語 --HTML 5 -File API 簡易教學

沒有留言: