偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

ASP.NET大文件上傳詳解

開(kāi)發(fā) 后端
本文向您介紹ASP.NET大文件上傳,通過(guò)Web上傳文件的原理及實(shí)現(xiàn)、ASP.NET的封裝至IIS流程主要講速HttpWorkerRequest性能。

做web開(kāi)發(fā)的都知道,在Web程序中上傳文件是很常見(jiàn)的需求。

利用HTTP協(xié)議上傳文件的方式非常有限,一般使用〈input type="file" / 〉標(biāo)簽來(lái)進(jìn)行上傳。

這種上傳方式會(huì)將內(nèi)容使用“multipart/form-data”進(jìn)行編碼(multipart/form-data規(guī)范原文),并將內(nèi)容POST到服務(wù)器端,然后進(jìn)行處理?!癿ultipart/form-data”相對(duì)于默認(rèn)的“application/x-url-encoded”,在大數(shù)據(jù)量提交時(shí)效率要高很多。使用〈input type="file" /〉標(biāo)簽上傳文件最大的好處在于各種服務(wù)器技術(shù)都對(duì)其最好了封裝,開(kāi)發(fā)起來(lái)能夠很直觀的對(duì)上傳的文件進(jìn)行處理。不過(guò)總體來(lái)說(shuō),這個(gè)協(xié)議并不適合做文件傳輸,解析數(shù)據(jù)流內(nèi)容的代價(jià)相對(duì)較高,并且沒(méi)有一些例如斷點(diǎn)續(xù)傳的機(jī)制來(lái)輔助,導(dǎo)致在上傳大文件時(shí)經(jīng)常會(huì)力不從心。

Web上傳文件的原理及實(shí)現(xiàn)

銀河使者的這篇文章從java語(yǔ)言介紹了通過(guò)〈input type="file" /〉標(biāo)簽把多文件從客戶(hù)端提交到服務(wù)器后進(jìn)行解析處理,.net版本大致相似。這樣就可以自己完成文件上傳的操作。

ASP.NET的封裝

ASP.NET 1.x 提供了一個(gè)HtmlInputFile控件,而2.0卻出現(xiàn)了一個(gè)新的控件FileUpload,但是它生成的html卻仍然是一樣的,在頁(yè)面中是用時(shí)需要這樣來(lái)定義:

[ASP.NET 1.x]

  1. 〈input id="MyFile" type="file" runat="server" /〉  

[ASP.NET 2.0]

  1. "FileUpload1" runat="server" />  

ASP.NET大文件上傳可以說(shuō)是低效率的代名詞,公平的所,IIS卻是它的幕后黑手。當(dāng)你選擇一個(gè)文件并且按下提交按鈕,IIS需要解析文件的所有內(nèi)容后,你才能讀取上傳的文件屬性,IIS5.X和IIS6都是這樣做的,好消息是IIS7.0將會(huì)使用Apache的方式。除非你現(xiàn)在就換到7.0,否則你只有長(zhǎng)時(shí)間等待直到上傳完畢,其余一無(wú)他法。你也不可以顯示進(jìn)度條因?yàn)槟銐焊恢涝谶@段時(shí)間里到底上傳了多少。

使用過(guò)FileUpload控件的都知道,它真是一把雙刃劍——既可能成為我們的救世主(a savior),也能是我們的敵人(an enemy ),其中一個(gè)很常見(jiàn)的問(wèn)題就是如何處理超過(guò)4MB的大文件上傳。不過(guò)我們應(yīng)該了解的是,之所以默認(rèn)的文件大小上限為4MB,并不是因?yàn)樵O(shè)計(jì)人員想當(dāng)然,而是為了避免潛在DOS攻擊危險(xiǎn)。

為了避免這個(gè)限制,需要修改配置文件的httpRuntime節(jié)的maxRequestLength屬性,文件越大,處理的時(shí)間也就越長(zhǎng),所以意味著通常你都要修改executionTimeout屬性,這個(gè)屬性1.X默認(rèn)是90s,2.0默認(rèn)是110s,大家可以看下machine.config文件,還有個(gè)shutdownTimeout屬性,不過(guò)我不知道它的用處。

IIS流程

當(dāng)ASP.NET大文件上傳到服務(wù)器上,不管你的maxRequestLength設(shè)置得多大,IIS都會(huì)提取完文件,然后ASP.NET根據(jù)system.web/httpRuntime節(jié)來(lái)判斷大小,超過(guò)了就會(huì)拋出一個(gè)異常,這個(gè)過(guò)程是由HttpRequest的GetEntireRawContent()方法,你可以看到:

  1.  HttpRuntimeSection httpRuntime = RuntimeConfig.  
  2. GetConfig(this._context).HttpRuntime;  
  3. int maxRequestLengthBytes = httpRuntime.  
  4. MaxRequestLengthBytes;  
  5. if (this.ContentLength  〉maxRequestLengthBytes)  
  6. {  
  7. if (!(this._wr is IIS7WorkerRequest))  
  8. {  
  9. this.Response.CloseConnectionAfterError();  
  10. }  
  11. throw new HttpException(SR.GetString  
  12. ("Max_request_length_exceeded"), null, 0xbbc);  
  13. }  

理論上說(shuō)可以使文件不是全部加載,但是能配置IIS讓它分塊讀取文件嗎?至少我還不知道!

ASP.NET的弊端

ASP.NET處理文件上傳的最大的問(wèn)題在于內(nèi)存占用太高,由于將整個(gè)文件載入內(nèi)存進(jìn)行處理,導(dǎo)致如果用戶(hù)上傳文件太大,或者同時(shí)上傳的用戶(hù)太多,會(huì)造成服務(wù)器端內(nèi)存耗盡。這個(gè)觀點(diǎn)其實(shí)是片面的,對(duì)于早期ASP.NET 1.X,為了供程序處理,會(huì)將用戶(hù)上傳的內(nèi)容完全載入內(nèi)存,這的確會(huì)帶來(lái)問(wèn)題,

但在ASP.NET 2.0中就已經(jīng)會(huì)在用戶(hù)上傳數(shù)據(jù)超過(guò)一定數(shù)量之后將其存在硬盤(pán)中的臨時(shí)文件中,而這點(diǎn)對(duì)于開(kāi)發(fā)人員完全透明,也就是說(shuō),開(kāi)發(fā)人員可以像以前一樣進(jìn)行數(shù)據(jù)流的處理,

這個(gè)也在httpRuntime里通過(guò)requestLengthDiskThreshold屬性來(lái)設(shè)置閾值(threshold),其默認(rèn)值為256,即一個(gè)請(qǐng)求內(nèi)容超過(guò)256KB時(shí)就會(huì)啟用硬盤(pán)作為緩存,這個(gè)閾值和客戶(hù)端是否是在上傳內(nèi)容無(wú)關(guān),只關(guān)心客戶(hù)端發(fā)來(lái)的請(qǐng)求大于這個(gè)值。

因此,在ASP.NET 2.0中服務(wù)器的內(nèi)存不會(huì)因?yàn)榭蛻?hù)端的異常請(qǐng)求而耗盡。

另外一個(gè)弊端就是當(dāng)請(qǐng)求超過(guò)maxRequestLength(默認(rèn)4M)之后,ASP.NET處理程序?qū)⒉粫?huì)處理該請(qǐng)求。這和ASP.NET拋出一個(gè)異常完全不同,這就是為什么如果用戶(hù)上傳文件太大,看到的并不是ASP.NET應(yīng)用程序中指定的錯(cuò)誤頁(yè)面(或者默認(rèn)的),因?yàn)锳SP.NET還沒(méi)有對(duì)這個(gè)請(qǐng)求進(jìn)行處理。

還有一個(gè)問(wèn)題就是處理ASP.NET大文件上傳的超時(shí)。

這個(gè)其實(shí)可以通過(guò)在運(yùn)行時(shí)讀取web.config中的httpRuntime節(jié),并轉(zhuǎn)化為HttpRuntimeSection對(duì)象或者重寫(xiě)Page.OnError()來(lái)檢測(cè)HTTP Code(相應(yīng)代碼)是否為400來(lái)處理,這里不再贅述,代碼如下:

  1. System.Configuration.Configuration   
  2. config = WebConfigurationManager.  
  3. OpenWebConfiguration("~");  
  4. HttpRuntimeSection section = config.GetSection  
  5. ("system.web/httpRuntime"as HttpRuntimeSection;  
  6. double maxFileSize = Math.Round  
  7. (section.MaxRequestLength / 1024.0, 1);  
  8. string errorString = string.Format("Make sure   
  9. your file is under {0:0.#} MB.", maxFileSize);  
  1. protected override void OnError(EventArgs e)  
  2. {  
  3. HttpContext ctx = HttpContext.Current;  
  4. Exception exception = ctx.Server.GetLastError ();  
  5.  
  6. string errorString =   
  7.  "
    Offending URL: "
     + ctx.Request.Url.ToString () +  
  8.  "
    Source: "
     + exception.Source +   
  9.  "
    Message: "
     + exception.Message +  
  10.  "
    Stack trace: "
     + exception.StackTrace;  
  11.  
  12. ctx.Response.Write (errorString);  
  13.  
  14. ctx.Server.ClearError ();  
  15.  
  16. base.OnError (e);  
  17. }  

對(duì)于文件上傳的功能需要較為特別的需求——例如進(jìn)度條提示,ASP.NET封裝的控件〈asp:FileUpload /〉就無(wú)能為力了?! ?/P>

好的解決方案

Robert Bazinet建議,最好的解決方案是使用RIA,大多數(shù)情況下,建議用Silverlight或Flash的上傳組件來(lái)替代傳統(tǒng)的FileUpload組件,這類(lèi)組件不只是提供了更好的上傳體驗(yàn),也比〈input type="file"〉標(biāo)簽在頁(yè)面上的文本框、按鈕漂亮,這個(gè)〈input type="file"〉標(biāo)簽并不能夠通過(guò)CSS添加樣式,不過(guò)也有人嘗試去解決了。至今為止并沒(méi)有什么商業(yè)上傳組件使用了Silverlight,不過(guò)這里有演示了用Silverlight進(jìn)行多文件上傳的示例程序。當(dāng)然使用Silverlight就可以很輕松的實(shí)現(xiàn)多線程上傳,斷點(diǎn)續(xù)傳這種功能了,這些都不是我要詳細(xì)討論的內(nèi)容,如果有需要可以自己去看下。

可選擇的解決方案

使用〈input type="file" /〉標(biāo)簽所能提供的支持非常有限,一些特殊需求我們不能實(shí)現(xiàn)——或者說(shuō)是無(wú)法輕易地、直接地實(shí)現(xiàn)。所以為了實(shí)現(xiàn)這樣的功能我們每次都要繞一個(gè)大大的彎。為了避免每次實(shí)現(xiàn)相同功能時(shí)都要費(fèi)神費(fèi)時(shí)地走一遍彎路,市面上或者開(kāi)源界出現(xiàn)了各種上傳組件,上傳組件提供了封裝好的功能,使得我們?cè)趯?shí)現(xiàn)文件上傳功能時(shí)變得輕松了很多。例如幾乎所有的上傳組件都直接或間接地提供了進(jìn)度提示的功能,有的提供了當(dāng)前的百分比數(shù)值,有的則直接提供了一套UI;有的組件只提供了簡(jiǎn)單的UI,有的卻提供了一整套上傳、刪除的管理界面。此外,有的組件還提供了防止客戶(hù)端惡意上傳的能力。

我覺(jué)得最好的辦法是在HttpModule里分塊讀取文件并且保持頁(yè)面激活的狀態(tài),這樣就不會(huì)超時(shí),同時(shí)也可以跟蹤進(jìn)度或者取消上傳,或者通過(guò)HttpHandler實(shí)現(xiàn),在通過(guò)進(jìn)度條給用戶(hù)充分提示的同時(shí),也讓開(kāi)發(fā)人員能夠更好地控制文件大小以及上傳過(guò)程中可能出現(xiàn)的異常。上傳組件都是用這些辦法的,我們的選擇有:

  1. FileUploader.NET (MediaChase公司,$310以上)   
  2. RadUpload (Telerik公司,$249)   
  3. NeatUpload (免費(fèi),遵守LGPL協(xié)議)   
  4. ······  

NeatUpload是在ASP.NET Pipeline的BeginRequest事件中截獲當(dāng)前的HttpWorkerRequest對(duì)象,然后直接調(diào)用其ReadEntityBody等方法獲取客戶(hù)端傳遞過(guò)來(lái)的數(shù)據(jù)流,并加以分析和處理。并通過(guò)使用新的請(qǐng)求進(jìn)行輪詢(xún)來(lái)獲取當(dāng)前上傳的狀態(tài)。關(guān)于NeatUpload和其他開(kāi)源組件的介紹可以參看JeffreyZhao的在ASP.NET應(yīng)用程序中上傳文件,當(dāng)然他還說(shuō)了Memba Velodoc XP Edition和swfupload,寫(xiě)的非常棒!

HttpWorkerRequest實(shí)現(xiàn)介紹

利用隱含的HttpWorkerRequest,用它的GetPreloadedEntityBody和ReadEntityBody方法從IIS為ASP.NET建立的pipe里分塊讀取數(shù)據(jù)可以實(shí)現(xiàn)文件上傳。實(shí)現(xiàn)方法如下:

  1. IServiceProvider provider=(IServiceProvider)  
  2. HttpContext.Current;  
  3. HttpWorkerRequest wr=(HttpWorkerRequest)  
  4. provider.GetService(typeof(HttpWorkerRequest));  
  5. byte[] bs=wr.GetPreloadedEntityBody();  
  6. if(!wr.IsEntireEntityBodyIsPreloaded())  
  7. {  
  8. int n=1024;  
  9. byte[] bs2=new byte[n];  
  10. while(wr.ReadEntityBody(bs2,n) 〉0)  
  11. {  
  12. }  
  13. }  

結(jié)論

ASP.NET大文件上傳是一個(gè)不完善和有缺陷的領(lǐng)域,相信在不久會(huì)得到提高和發(fā)展,如果你已經(jīng)解決了,說(shuō)明你在一個(gè)好公司,否則你可以考慮使用第三方產(chǎn)品來(lái)解決了。文件上傳的問(wèn)題,我們都能夠找到很多種不同的方法來(lái)解決,挑戰(zhàn)在于找出不同做法的利弊然后找到一個(gè)適用于自己項(xiàng)目的方案,這不僅僅是在文件上傳這一個(gè)方面!

【編輯推薦】

  1. ASP.NET環(huán)境下的Shell函數(shù)
  2. 在ASP.NET中向數(shù)據(jù)庫(kù)批量插入數(shù)據(jù)
  3. ASP.NET用Post方式向網(wǎng)頁(yè)發(fā)送數(shù)據(jù)
  4. ASP.NET 2.0部署WEB應(yīng)用程序淺析
  5. ASP.NET中的HttpWorkerRequest對(duì)像
責(zé)任編輯:冰荷 來(lái)源: cnblogs
相關(guān)推薦

2009-07-20 16:09:39

2009-07-21 16:05:58

ASP.NET大文件上

2009-07-24 15:07:56

ASP.NET上傳文件

2010-02-05 08:32:32

ASP.NET MVC

2009-07-29 10:02:49

ASP.NET上傳

2009-07-29 16:08:07

ASP和ASP.NET

2009-10-30 14:03:59

ASP.NET上傳文件

2009-07-21 13:01:07

ASP.NET上傳文件

2009-07-27 17:32:39

Web ServiceASP.NET

2009-07-22 16:25:41

ASP.NET AJA

2009-07-24 10:14:22

ASP.NET開(kāi)發(fā)

2009-07-28 16:57:50

ASP.NET Ses

2009-08-05 11:14:33

ASP.NET ISA

2009-07-23 13:19:51

2017-03-06 11:13:57

ASP.NETCoreMVC

2009-07-21 16:23:57

2009-07-30 14:18:02

ASP.NET實(shí)例教程

2009-08-04 11:46:09

2023-09-06 08:33:30

2015-03-03 13:15:19

ASP.NET大文件下載實(shí)現(xiàn)思路
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)