前言:
首先對於圖片上傳而言,在我們的專案開發中可以說出現的頻率是相當的高的。這篇文章中,我將要描述的是在我們.Net中如何使用Jquery Ajax通過FormData物件非同步提交圖片檔案到後臺儲存,並返回儲存的圖片路徑展示出圖片,實現一個無重新整理的非同步圖片上傳的過程,當然這裡我講解的是單張圖片的儲存過程,對於多圖片上傳的話其實我們只需要在type='file'文字框中加上一個multiple可多選,然後獲取input中的檔案陣列遍歷向後臺提交感興趣的話可以嘗試,不過下一篇部落格將會講解如何使用Layui上傳多張圖片到服務端儲存。
FormData物件概述:
FormData物件是H5中的一個新特性,用以將資料編譯成鍵值對,以便用XMLHttpRequest來傳送資料。其主要用於傳送表單資料,但亦可用於傳送帶鍵資料(keyed data),而獨立於表單使用。如果表單enctype屬性設為multipart/form-data ,則會使用表單的submit()方法來傳送資料,從而,傳送資料具有同樣形式。比起普通的ajax,使用FormData的最大優點就是我們可以非同步上傳一個二進位制檔案。
關於FormData物件的使用參考文章:https://developer.mozilla.org/zh-CN/docs/Web/API/FormData/Using_FormData_Objects
Jquery Ajax通過FormData物件非同步提交圖片檔案:
HTML中選中圖片的按鈕:
<div>頭像</div> <div class="tuxiang-up" id="headPortrait" style="background-image:url(/Content/ExSys/images/ktoux.jpg))"> <input type="file" onchange="uploadImage(this)"> <!--點選上傳按鈕後,圖片縮圖以上級背景圖片顯示--> </div>
Jquery中FormData二進位制檔案物件拼接和提交:
<script type="text/javascript"> //使用者頭像修改 function uploadImage(obj) { var formData = new FormData();//建立FormData物件,以鍵值對的方式拼接form表單資料(multipart/form-data,圖片媒體檔案) //獲取input中的檔案列表資訊 var files = $(obj).prop("files"); //拼接圖片檔案流資訊 console.log(files[0]); formData.append("file", files[0]); $.ajax({ url: "/FileUpload/FileLoad/", type: 'POST', data: formData, async: false, dataType: "json", // 告訴jQuery不要去處理髮送的資料 processData: false, // 告訴jQuery不要去設定Content-Type請求頭 contentType: false, beforeSend: function () { console.log("正在進行,請稍候"); }, success: function (data) { if (data.isSuccess) { console.log(data.path); console.log("圖片上傳成功"); //動態賦值 $("#headPortrait").css("background-image", "url(" + data.path + ")"); } else { console.log("網路異常,請稍後再試"); } }, error: function (data) { console.log("error2"); } }); } </script>
服務端接收Ajax非同步提交的二進位制圖片檔案資訊,並儲存:
1public class FileUploadController : Controller 2{ 3/// <summary> 4 /// 對驗證和處理 HTML 窗體中的輸入資料所需的資訊進行封裝,如FromData拼接而成的檔案 5 /// </summary> 6 /// <param name="context">FemContext對驗證和處理html窗體中輸入的資料進行封裝</param> 7 /// <returns></returns> 8 [HttpPost] 9 public ActionResult FileLoad(FormContext context) 10 { 11 HttpPostedFileBase httpPostedFileBase = Request.Files[0];//獲取二進位制圖片檔案流 12 if (httpPostedFileBase != null) 13 { 14 try 15 { 16 ControllerContext.HttpContext.Request.ContentEncoding = Encoding.GetEncoding("UTF-8"); 17 ControllerContext.HttpContext.Response.Charset = "UTF-8"; 18 19 string fileName = Path.GetFileName(httpPostedFileBase.FileName);//原始檔名稱 20 string fileExtension = Path.GetExtension(fileName);//副檔名 21 22 byte[] fileData = ReadFileBytes(httpPostedFileBase);//檔案流轉化為二進位制位元組 23 24 string result = SaveFile(fileExtension, fileData);//檔案儲存 25 if (string.IsNullOrEmpty(result)) 26 { 27 return Json(new { isSuccess = false, path = "",errorMsg= "上傳檔案失敗"}); 28 } 29 30 return Json(new { isSuccess = true, path = result }); 31 } 32 catch (Exception ex) 33 { 34 return Json(new { isSuccess = false, path = "" }); 35 } 36 } 37 else 38 { 39 return Json(new { isSuccess = false, path = "" }); 40 } 41 } 42 43 44 /// <summary> 45 /// 將檔案流轉化為二進位制位元組 46 /// </summary> 47 /// <param name="fileData">圖片檔案流</param> 48 /// <returns></returns> 49 private byte[] ReadFileBytes(HttpPostedFileBase fileData) 50 { 51 byte[] data; 52 using (Stream inputStream = fileData.InputStream) 53 { 54 MemoryStream memoryStream = inputStream as MemoryStream; 55 if (memoryStream == null) 56 { 57 memoryStream = new MemoryStream(); 58 inputStream.CopyTo(memoryStream); 59 } 60 data = memoryStream.ToArray(); 61 } 62 return data; 63 } 64 65 /// <summary> 66 /// 儲存檔案 67 /// </summary> 68 /// <param name="fileExtension">副檔名</param> 69 /// <param name="fileData">圖片二進位制檔案資訊</param> 70 /// <returns></returns> 71 private string SaveFile(string fileExtension, byte[] fileData) 72 { 73 string result; 74 try 75 { 76 77 string saveName = Guid.NewGuid().ToString()+ fileExtension; //儲存檔名稱 78 79 // 檔案上傳後的儲存路徑 80 string basePath = "UploadFile"; 81 string saveDir = DateTime.Now.ToString("yyyy-MM-dd"); 82 string savePath = System.IO.Path.Combine(saveDir, saveName); 83 84 string serverDir = System.IO.Path.Combine(Server.MapPath("~/"), basePath, saveDir); 85 if (!System.IO.Directory.Exists(serverDir)) 86 { 87 System.IO.Directory.CreateDirectory(serverDir); 88 } 89 string fileNme = System.IO.Path.Combine(serverDir, saveName);//儲存檔案完整路徑 90 System.IO.File.WriteAllBytes(fileNme, fileData);//WriteAllBytes建立一個新的檔案,按照對應的檔案流寫入,假如已存在則覆蓋 91 //返回完整的圖片儲存地址 92 result="/"+basePath + "/" + saveDir + "/" + saveName; 93 } 94 catch (Exception) 95 { 96 result = "發生錯誤"; 97 } 98 return result; 100 } 101 }