[Memo]ASP.NET上傳檔案超過限制大小時,導至特定頁面(by Global.asax)
前言
ASP.NET上傳檔案時,最大限制大小是2GB,預設是4MB。
要調整的話,可以在web.config上加上
<system.web>
<httpRuntime maxRequestLength="4096" executionTimeout="43200"/>
</system.web>
如果都沒做任何處理,當使用ASP.NET的FileUpload控制項時,
當上傳檔案超過config限制大小時,將無法顯示自訂錯誤網頁。
Microsoft Internet Explorer 會顯示「找不到伺服器或 DNS」錯誤訊息作為替代。
Survey Solution
網路上有許多相對應的解法,可以參考:
- 黃忠成老師:ASP.NET 檔案上傳處理—檔案大小超過限制之處理
- 邱英瑞(Jacky)老師:ASP.NET 無法上載大型檔案(大於 4MB)
- MSDN forum:如何檢查上傳檔案大小?? (包括使用javascript裡用ActiveX檢查)
不過黃忠成老師的方式,不知道為什麼我試不出來,程式都有進入中斷點跑過,
甚至也已經可以導到我自訂的頁面裡面的PageLoad事件,
但是最後呈現出來的頁面,仍然是FileUpload那一頁的網址,錯誤頁面仍如上面所述。
黃老師的方法應該是沒錯,當我把config設定到2GB的時候,在程式裡面則是控制不可以上傳超過4MB,
那黃老師的方法就可以正常work,但假設上傳的檔案超過config的限制時,
程式一樣會跑,但錯誤頁面就不是自訂的了。
加上老師的作法,是給UpdatePanel+iFrame+FileUpload使用,
小的這邊的需求則是希望可以直接在Global就解決掉。
所以就找到了另一個參考:ASP Net - How to handle "Maximum request length exceeded" exception
Play it
這邊順便記錄一下,方便以後還有其他人可以直接使用。
在Global.asax裡面覆寫Application_BeginRequest()的方法:
protected void Application_BeginRequest(Object sender, EventArgs e)
{
System.Web.Configuration.HttpRuntimeSection runTime = (System.Web.Configuration.HttpRuntimeSection)System.Web.Configuration.WebConfigurationManager.GetSection("system.web/httpRuntime");
//Approx 100 Kb(for page content) size has been deducted because the maxRequestLength proprty is the page size, not only the file upload size
int maxRequestLength = (runTime.MaxRequestLength - 100) * 1024;
//This code is used to check the request length of the page and if the request length is greater than
//MaxRequestLength then retrun to the same page with extra query string value action=exception
HttpContext context = ((HttpApplication)sender).Context;
if (context.Request.ContentLength > maxRequestLength)
{
IServiceProvider provider = (IServiceProvider)context;
HttpWorkerRequest workerRequest = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));
// Check if body contains data
if (workerRequest.HasEntityBody())
{
// get the total body length
int requestLength = workerRequest.GetTotalEntityBodyLength();
// Get the initial bytes loaded
int initialBytes = 0;
if (workerRequest.GetPreloadedEntityBody() != null)
initialBytes = workerRequest.GetPreloadedEntityBody().Length;
if (!workerRequest.IsEntireEntityBodyIsPreloaded())
{
byte[] buffer = new byte[512000];
// Set the received bytes to initial bytes before start reading
int receivedBytes = initialBytes;
while (requestLength - receivedBytes >= initialBytes)
{
// Read another set of bytes
initialBytes = workerRequest.ReadEntityBody(buffer, buffer.Length);
// Update the received bytes
receivedBytes += initialBytes;
}
initialBytes = workerRequest.ReadEntityBody(buffer, requestLength - receivedBytes);
}
}
// Redirect the user to the same page with querystring action=exception.
context.Response.Redirect(this.Request.Url.LocalPath + "?action=exception");
}
}
結論
雖說這個方式可以work,但是當上傳的檔案太大時,
等待導頁的時間,仍然相當漫長,這一點要特別注意。
[註]2010/01/15,補充一下bauann與小朱大推薦的silverlight fileupload,相當相當不錯用:Silverlight File Upload
blog 與課程更新內容,請前往新站位置:http://tdd.best/