上文ASP.NET MVC 文件上傳教程(一)我們講了簡單的上傳以及需要注意的地方,查相關(guān)資料時(shí),感覺上傳里面涉及到的內(nèi)容還是比較多,于是就將上傳這一塊分為幾節(jié)來處理,同時(shí)后續(xù)也會(huì)講到關(guān)于做上傳時(shí)遺漏的C#應(yīng)該注意的地方,及時(shí)進(jìn)行查漏補(bǔ)缺,盡量將這一塊完善起來。
引入
上一節(jié)我們講到了上傳這一塊,有朋友提出未涉及到大文件的上傳這一塊,思前想后還是來試著做做,畢竟之前沒怎么去仔細(xì)考慮過這個(gè)問題,尤其還可以聯(lián)系實(shí)際開發(fā)中創(chuàng)建文件夾等一系列問題,同時(shí)關(guān)于上傳在網(wǎng)上隨便找找都充斥著大量的組件,我們何必再去造輪子,我需要做的是只是對(duì)基礎(chǔ)的回顧以及進(jìn)一步深入以及在做的過程中發(fā)現(xiàn)一些細(xì)節(jié)性的問題并解決就足矣,不喜勿噴。
深入上傳
再次聲明對(duì)于上傳可以顯示上傳進(jìn)度之類我們不去做過多探討,有這樣的組件,自行去找,我們只需實(shí)現(xiàn)比較核心的這一塊即可。
我們可以想象這一樣一個(gè)場(chǎng)景:比如在博客園中,每個(gè)博客者都可以上傳文件如圖片、腳本之類,我們可以通過園友名稱來創(chuàng)建每個(gè)園友上傳的文件,接下來我們來實(shí)現(xiàn)這樣的一個(gè)場(chǎng)景。
既然是對(duì)應(yīng)博客的名稱創(chuàng)建文件,也就是需要對(duì)應(yīng)的博客這樣的一個(gè)類。如下:
public class BlogSample
{
public string UserName { get; set; }
public string Id { get; set; }
}
我們通過博客名稱來創(chuàng)建文件夾并在該文件夾下以唯一的Id來創(chuàng)建子文件夾,在該Id文件夾下的附件( atttachment )中存儲(chǔ)上傳的文件。接下來我們需要梳理整個(gè)上傳文件的過程。難道就把要上傳的文件直接到上傳到對(duì)應(yīng)的文件夾嗎,這么做顯然不是最優(yōu)的,當(dāng)有上傳中斷時(shí)則在文件夾創(chuàng)建的文件不是完整的則是垃圾文件,而我們直接先創(chuàng)建一個(gè)臨時(shí)文件,即使上傳失敗我們可以定期清理臨時(shí)文件也就是垃圾文件,若未中斷,上傳完畢時(shí)則將臨時(shí)文件移動(dòng)到我們對(duì)應(yīng)的文件夾中。通過我們實(shí)際下載文件時(shí)很明顯看的出也是這么做的。接下來我們開始進(jìn)行實(shí)現(xiàn)。
(1)我們給出一個(gè)關(guān)于上傳的 UploadManager 靜態(tài)類,我們可以寫死上傳的文件夾名稱或者通過配置文件自定義上傳文件夾名稱。
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);
}
上述已經(jīng)表明可以自定義上傳文件夾在配置文件中(給出上傳虛擬路徑),例如如下:
!--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);
//若上傳文件夾中子文件夾未存在則創(chuàng)建
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();
}
//上傳完畢將臨時(shí)文件移動(dòng)到目標(biāo)文件
File.Move(tempPath, targetPath);
}
}
catch (Exception)
{
// 若上傳出錯(cuò),則刪除上傳到文件夾文件
if (File.Exists(targetPath))
File.Delete(targetPath);
// 刪除臨時(shí)文件
if (File.Exists(tempPath))
File.Delete(tempPath);
return false;
}
finally
{
// 刪除臨時(shí)文件
if (File.Exists(tempPath))
File.Delete(tempPath);
}
return true;
}
(3)循環(huán)讀取流到文件流中
/// summary>
/// 循環(huán)讀取流到文件流中
/// /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)開始寫入測(cè)試數(shù)據(jù),進(jìn)行調(diào)用方法:
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();
}
接下來我們來進(jìn)行測(cè)試,通過上傳一個(gè)84M的文件來看看效果(稍等片刻,文件有點(diǎn)大)。
![](http://img.jbzj.com/file_images/article/201605/2016524105228651.gif?2016424105239)
不好意思,令我大失所望,和昨天出現(xiàn)的錯(cuò)誤不一樣,今天出錯(cuò)是:超過最大請(qǐng)求長度。我們接下來再來看看昨天所說,我的IIS為10.0,也就是在IIS 7+上,通過昨天那樣設(shè)置應(yīng)該是沒問題的,難道和另外一個(gè)設(shè)置有關(guān)嗎,我們看看配置文件中的配置。
httpRuntime targetFramework="4.5"/>
未進(jìn)行設(shè)置,超過其默認(rèn)設(shè)置28.6M就出錯(cuò)了嗎,我們?cè)僭O(shè)置為2G看看。
httpRuntime targetFramework="4.5" executionTimeout="1100" maxRequestLength="2147483647"/>
![](http://img.jbzj.com/file_images/article/201605/2016524105324811.gif?2016424105334)
好,上傳成功也未出現(xiàn)上述錯(cuò)誤。
結(jié)語
這一節(jié)我們講了一下利用流來進(jìn)行大文件的處理,不過還是出現(xiàn)了一點(diǎn)小問題,和昨天再一起做一次總結(jié):
(1)在IIS 5和IIS 6中,默認(rèn)文件上傳的最大為4兆,當(dāng)上傳的文件大小超過4兆時(shí),則會(huì)得到錯(cuò)誤信息,但是我們通過如下來設(shè)置文件大小。
system.web>
httpRuntime maxRequestLength="2147483647" executionTimeout="100000" />
/system.web>
(2)在IIS 7+,默認(rèn)文件上傳的最大為28.6兆,當(dāng)超過其默認(rèn)設(shè)置大小,同樣會(huì)得到錯(cuò)誤信息,但是我們卻可以通過如下來設(shè)置文件上傳大?。ㄍ瑫r(shí)也要進(jìn)行如上設(shè)置)。
system.webServer>
security>
requestFiltering>
requestLimits maxAllowedContentLength="2147483647" />
/requestFiltering>
/security>
/system.webServer>
關(guān)于在配置文件中如何設(shè)置文件大小而不出錯(cuò),總算做了一個(gè)最終的總結(jié),有收獲,繼續(xù)Fighting。
本文作者:Recluse_Xpy
本文鏈接:http://www.cnblogs.com/CreateMyself/p/5419594.html
以上就是關(guān)于ASP.NET MVC 文件上傳的全部內(nèi)容介紹,希望對(duì)大家的學(xué)習(xí)有所幫助。
您可能感興趣的文章:- ASP.NET MVC HttpPostedFileBase文件上傳的實(shí)例代碼
- ASP.NET MVC4 利用uploadify.js多文件上傳
- asp.net core mvc實(shí)現(xiàn)文件上傳實(shí)例
- asp.net mvc 實(shí)現(xiàn)文件上傳帶進(jìn)度條的思路與方法
- 解決ASP.NET Core Mvc文件上傳限制問題實(shí)例
- ASP.NET MVC 文件上傳教程(一)
- ASP.NET MVC5實(shí)現(xiàn)文件上傳與地址變化處理(5)
- ASP.NET MVC處理文件上傳的小例子
- 用Fine Uploader+ASP.NET MVC實(shí)現(xiàn)ajax文件上傳[代碼示例]
- ASP.NET MVC實(shí)現(xiàn)批量文件上傳