上文ASP.NET MVC 檔案上傳教程(一)我們講了簡單的上傳以及需要注意的地方,查相關資料時,感覺上傳裡面涉及到的內容還是比較多,於是就將上傳這一塊分為幾節來處理,同時後續也會講到關於做上傳時遺漏的C#應該注意的地方,及時進行查漏補缺,盡量將這一塊完善起來。
引入
上一節我們講到了上傳這一塊,有朋友提出未涉及到大檔案的上傳這一塊,思前想後還是來試著做做,畢竟之前沒怎麼去仔細考慮過這個問題,尤其還可以聯絡實際開發中建立檔案夾等一系列問題,同時關於上傳在網上隨便找找都充斥著大量的組件,我們何必再去造輪子,我需要做的是只是對基礎的回顧以及進一步深入以及在做的過程中發現一些細節性的問題並解決就足矣,不喜勿噴。
深入上傳
再次聲明對於上傳可以顯示上傳進度之類我們不去做過多探討,有這樣的組件,自行去找,我們只需實現比較核心的這一塊即可。
我們可以想象這一樣一個情境:比如在部落格園中,每個部落格者都可以上傳檔案如圖片、指令碼之類,我們可以通過園友名稱來建立每個園友上傳的檔案,接下來我們來實現這樣的一個情境。
既然是對應部落格的名稱建立檔案,也就是需要對應的部落格這樣的一個類。如下:
public class BlogSample { public string UserName { get; set; } public string Id { get; set; } }
我們通過部落格名稱來建立檔案夾並在該檔案夾下以唯一的Id來建立子檔案夾,在該Id檔案夾下的附件( atttachment )中儲存上傳的檔案。接下來我們需要梳理整個上傳檔案的過程。難道就把要上傳的檔案直接到上傳到對應的檔案夾嗎,這麼做顯然不是最優的,當有上傳中斷時則在檔案夾建立的檔案不是完整的則是垃圾檔案,而我們直接先建立一個臨時檔案,即使上傳失敗我們可以定期清理臨時檔案也就是垃圾檔案,若未中斷,上傳完畢時則將臨時檔案移動到我們對應的檔案夾中。通過我們實際下載檔案時很明顯看的出也是這麼做的。接下來我們開始進行實現。
(1)我們給出一個關於上傳的 UploadManager 靜態類,我們可以寫死上傳的檔案夾名稱或者通過設定檔自訂上傳檔案夾名稱。
static UploadManager() { //從設定檔中擷取上傳檔案夾 if (String.IsNullOrWhiteSpace(WebConfigurationManager.AppSettings["UploadFolder"])) UploadFolderRelativePath = @"~/upload"; else UploadFolderRelativePath = WebConfigurationManager.AppSettings["UploadFolder"]; UploadFolderPhysicalPath = HostingEnvironment.MapPath(UploadFolderRelativePath); if (!Directory.Exists(UploadFolderPhysicalPath)) Directory.CreateDirectory(UploadFolderPhysicalPath); }
上述已經表明可以自訂上傳檔案夾在設定檔中(給出上傳虛擬路徑),例如如下:
<!--<add key="UploadFolder" value="~/UploadFile/">-->
(2)儲存檔案的核心方法
[SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times")] public static bool SaveFile(Stream stream, string fileName, string userName, string guid) { string tempPath = string.Empty, targetPath = string.Empty; try { string tempFileName = GetTempFilePath(fileName); if (userName != null) { var contentType = userName; var contentId = guid; tempPath = GetTempFilePath(tempFileName); targetPath = GetTargetFilePath(fileName, contentType, contentId, string.Empty, FilesSubdir); //若上傳檔案夾中子檔案夾未存在則建立 var file = new FileInfo(targetPath); if (file.Directory != null && !file.Directory.Exists) file.Directory.Create(); using (FileStream fs = File.Open(tempPath, FileMode.Append)) { if (stream.Length > 0) { SaveFile(stream, fs); } fs.Close(); } //上傳完畢將臨時檔案移動到目標檔案 File.Move(tempPath, targetPath); } } catch (Exception) { // 若上傳出錯,則刪除上傳到檔案夾檔案 if (File.Exists(targetPath)) File.Delete(targetPath); // 刪除臨時檔案 if (File.Exists(tempPath)) File.Delete(tempPath); return false; } finally { // 刪除臨時檔案 if (File.Exists(tempPath)) File.Delete(tempPath); } return true; }
(3)迴圈讀取流到檔案流中
/// <summary> /// 迴圈讀取流到檔案流中 /// </summary> /// <param name="stream"></param> /// <param name="fs"></param> public static void SaveFile(Stream stream, FileStream fs) { var buffer = new byte[4096]; int bytesRead; while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0) { fs.Write(buffer, 0, bytesRead); } }
(4)開始寫入測試資料,進行調用方法:
var testSample = new BlogSample() { UserName = "xpy0928", Id = Guid.NewGuid().ToString("N") }; if (ModelState.IsValid) { var fileName = bModel.BlogPhoto.FileName; var success = UploadManager.SaveFile(bModel.BlogPhoto.InputStream, fileName, testSample.UserName, testSample.Id); if (!success) { // TODO(your code) } //var filePath = Server.MapPath(string.Format("~/{0}", "File")); //bModel.BlogPhoto.SaveAs(Path.Combine(filePath, fileName)); ModelState.Clear(); }
接下來我們來進行測試,通過上傳一個84M的檔案來看看效果(稍等片刻,檔案有點大)。
不好意思,令我大失所望,和昨天出現的錯誤不一樣,今天出錯是:超過最大請求長度。我們接下來再來看看昨天所說,我的IIS為10.0,也就是在IIS 7+上,通過昨天那樣設定應該是沒問題的,難道和另外一個設定有關嗎,我們看看設定檔中的配置。
<httpRuntime targetFramework="4.5"/>
未進行設定,超過其預設設定28.6M就出錯了嗎,我們再設定為2G看看。
<httpRuntime targetFramework="4.5" executionTimeout="1100" maxRequestLength="2147483647"/>
好,上傳成功也未出現上述錯誤。
結語
這一節我們講了一下利用流來進行大檔案的處理,不過還是出現了一點小問題,和昨天再一起做一次總結:
(1)在IIS 5和IIS 6中,預設檔案上傳的最大為4兆,當上傳的檔案大小超過4兆時,則會得到錯誤資訊,但是我們通過如下來設定檔案大小。
<system.web> <httpRuntime maxRequestLength="2147483647" executionTimeout="100000" /></system.web>
(2)在IIS 7+,預設檔案上傳的最大為28.6兆,當超過其預設設定大小,同樣會得到錯誤資訊,但是我們卻可以通過如下來設定檔案上傳大小(同時也要進行如上設定)。
<system.webServer> <security> <requestFiltering> <requestLimits maxAllowedContentLength="2147483647" /> </requestFiltering> </security></system.webServer>
關於在設定檔中如何設定檔案大小而不出錯,總算做了一個最終的總結,有收穫,繼續Fighting。
本文作者:Recluse_Xpy
本文連結:http://www.cnblogs.com/CreateMyself/p/5419594.html
以上就是關於ASP.NET MVC 檔案上傳的全部內容介紹,希望對大家的學習有所協助。