您的位置:首页 > 编程语言 > ASP

ASP.NET 用.Net的File控件上传文件大文件上传之异常处理 的解决方案

2010-10-21 13:51 681 查看
最近一个项目需要用到HTTP文件上传功能,做过类似功能的朋友都知道,实现HTTP文件上传的功能并不难,使用ASP.NET就更加方便了,服务器端控件HtmlInputFile提供了强大的支持。一切进展得很顺利,功能很快就实现了,套用电视剧《美丽的田野》里那位周期性出现的家伙的一个词:一切看上去都十分“美观”。srxljl

但是当尝试上传较大的文件时,一切似乎变得“丑陋”起来—程序崩溃,而且出现“The
page cannot be
displayed”的错误页面。查阅相关资料后得知ASP.NET中默认的上传文件的最大值为4M,在web.config中可进行设置,但是即使设得再大,用户上传的文件都有可能超过限制。于是想到在Global.asax中的Application_Error事件处理过程中捕获“Maximum
request length
exceeded.”异常然后使页面Redirect至Custom
Error
Page。然而这个方法也行不通,虽然在Application_Error中可以捕获到“Maximum
request length
exceeded.”异常,但是页面无法Redirect至Custom
Error Page,依旧是“The page cannot be
displayed”。srxljl
事情一下变得棘手起来,很多技术文章也说这是HTTP协议为保证web服务器的稳定及安全所设的限制。就连微软官方的Support上也写着:“When the maxRequestLength attribute is
set in the Machine.config file and then a request is posted (for example, a file
upload) that exceeds the value of maxRequestLength, a custom
error page cannot be displayed. Instead, Microsoft Internet Explorer will
display a "Cannot find server or DNS" error
message.”这看似一个受协议限制的无解问题。正当我打算就此作罢之际,无意间看到一片文章,根据其上所写的方案,这个问题居然解决了,真是山穷水复疑无路,柳暗花明又一村。
现将该方案按照我的思路整理出来,一来做一下总结,二来希望能对他人有所帮助。这固然有事后孔明之嫌,但毕竟还是好处多多。srxljl
前面说过,等Application_Error事件处理捕获到“Maximum
request length
exceeded.”异常为时已晚,页面已无法正常Redirect至Custom
Error Page,因此应该设法使系统不抛出“Maximum request length
exceeded.”异常。而要使系统不抛出该异常,就应在HttpHandler处理Request之前,使HttpHandler得到的HttpContext的内容小于maxRequestLength。看来,可以在Global.asax中的Application_BeginRequest事件处理过程中作一番文章。下面的代码就给出了解决方案:
1

private void
Application_BeginRequest(Object source, EventArgs e)
2



        

{
3

             
HttpRequest request = HttpContext.Current.Request;
4

            if
(request.ContentLength > 4096000)//4096000 is maxRequestLength
5



            

{
6

                 
HttpApplication app = source as
HttpApplication;
7

                 
HttpContext context = app.Context;
8

            
9

                 
HttpWorkerRequest wr =
10

                     
(HttpWorkerRequest)(context.GetType().GetProperty
11

                     
("WorkerRequest",
BindingFlags.Instance |
12

                     
BindingFlags.NonPublic).GetValue(context, null));
13

                byte[]
buffer;
14

                if
(wr.HasEntityBody())
15



                

{
16

                    int contentlen
=
Convert.ToInt32(wr.GetKnownRequestHeader(
17


18

                         
HttpWorkerRequest.HeaderContentLength));
19

                     
buffer =
wr.GetPreloadedEntityBody();
20

                    int received
=
buffer.Length;
21

                    int totalrecv
=
received;
22

                    if (!wr.IsEntireEntityBodyIsPreloaded())
23



                    

{
24

                         
buffer =
new
byte[65535];
25

                        while ( contentlen
-
totalrecv >= received )
26



                        

{
27

                             
received =
28

                                 
wr.ReadEntityBody(buffer,
29

                                 
buffer.Length);
30

                             
totalrecv += received;
31

                         
}
32

                         
received =
33

                             
wr.ReadEntityBody(buffer, contentlen -
totalrecv);
34

                     
}
35

                 
}
36

                 
context.Response.Redirect("../error.aspx");//Redirect to custom
error page.
37

             
}    从代码可以看出,关键的思路就是:如果上传的文件超过maxRequestLength,则上传文件已可以看作无效文件,于是就可以放心大胆的为其瘦身,使Request的HttpContext的内容小于maxRequestLength,这样“Maximum
request length exceeded.”异常就不会再产生,页面也就可以正常跳转到Custom
Error
Page了。代码中的循环部分就是将上传的文件内容读入buffer中,因为上传文件已属于无效文件,所以文件内容也就不重要,这里buffer的用途仅仅是用来接收上传文件内容,buffer中的数据也无需再被读取。
 

一个本来看似无解的问题就这样解决了,虽然凭的不是一己之力,但仍然收获颇丰,所以感觉自然仍是十分“美观”!

来源:http://www.cnblogs.com/2bno1/archive/2005/11/28/285893.html

更多搜索:asp.net 大文件上传 大文件上传组件 fileupload控件  上传控件 asp.net 上传控件

用.Net的File控件上传文件的解决方案
(1)srxljl

在遍历了csdn中所有关于上传大文件的帖子以后,写了这篇垃圾。(:-))

上传大文件,有好几种方法:

1、思归的HttpWorkerRequest方法,太难,看不懂:-(
2、利用第三方的控件 AspNetUpload
要钱!!算了,咱还是喜欢免费的。
3、修改web.config文件,但是不能捕获错误。
4、通过ftp的方式上传。服务器需要提供ftp服务。

没辙,只好选第三种方式,谁让咱太蠢了呢!(太蠢了,没有关系,要多吃鱼,听说吃鱼能聪明点。)

那就仔细专研第三种方式吧!

修改Webcong文件:

 

<system.web>
<httpRuntime maxRequestLength="40690"
           useFullyQualifiedRedirectUrl="true"
           executionTimeout="6000"
           useFullyQualifiedRedirectUrl="false"
       minFreeThreads="8"
       minLocalRequestFreeThreads="4"
        appRequestQueueLimit="100"
        enableVersionHeader="true"
           />
</system.web>

其中与上传有密切关系的是: srxljl

maxRequestLength

指示 ASP.NET 支持的最大文件上载大小。

该限制可用于防止因用户将大量文件传递到该服务器而导致的拒绝服务攻击。

指定的大小以 KB 为单位。

默认值为 4096 KB (4 MB)。

executionTimeout

指示在被 ASP.NET 自动关闭前,允许执行请求的最大秒数。

单位为秒,在上传大的文件时把这个设的大一些。

如果服务器内存512M,已可上传大小160M的文件。(没试过,csdn上众帖子的一致意见。)

到这里web.config的设置就已经结束。

用.Net的File控件上传文件的解决方案 (2)srxljl

 

可是一旦上传文件的大小超过了这个设置的文件大小范围就会发生如下错误:

该页无法显示 srxljl

您要查看的页当前不可用。网站可能遇到技术问题,或者您需要调整浏览器设置。

虽然解决不了,那也要捕获这个错误啊!怎么办呢?

最近吃了几条鱼,想了想,由于这个错误是由file控件引发的前台错误,所以在后台想利用try...catch来捕获是行不通的。

于是想到了利用.NET的错误捕获页面的机制来处理。可行哦。 srxljl

 

1、先设置web.config
    <customErrors mode="On"/>
2、新建一个error.aspx 文件,专门用来捕获错误的。
3、在上传文件的aspx页面的前台页面里添加page指令。ErrorPage="UploadError.aspx"
4、在error.aspx中添加一些代码来判断错误信息是否是file引起的前台错误。
     public class UploadError : System.Web.UI.Page
     {
      private void Page_Load(object sender, System.EventArgs e)
      {
       Exception ex = Server.GetLastError();
       if (ex != null)
       {
        Response.Redirect("../error.aspx");
       }
       else //前台错误ex为空值
       {    
        Response.Redirect("uploadexcel.aspx?err=1"); //重新跳转到上传页面,
加上err参数是为了显示错误信息
       }
      }
     
5、显示错误提示。
     public class uploadexcel : System.Web.UI.Page
     {
      private void Page_Load(object sender, System.EventArgs e)
      {
       if (Request["err"] == "1")
       {
       Page.RegisterStartupScript("budget","<script language = javascript>
alert('Upload file has failed ! File size is too large !')</script>");
       }
      }
     }
6、搞定收工。(这鱼没有白吃啊)
经过上述修改,现在的上传变成了,程序指定文件大小,如果超过,则弹出错误提示。
这样一来,就好多了,最起码自己能接受了,跟用户解释也不太费劲了。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐