抓取“Maximum request length exceeded”错误

113
我正在编写一个上传函数,当上传的文件超过了在web.config中指定的最大大小(最大大小设置为5120)时,遇到了捕获“System.Web.HttpException: Maximum request length exceeded”的问题。我使用一个简单的文件输入框。
问题是异常在上传按钮的点击事件之前被抛出,而这个异常发生在我的代码运行之前。那么我该如何捕获和处理这个异常?
编辑:异常是立即抛出的,所以我很确定这不是由于网络连接较慢而导致的超时问题。

5
有人尝试过在MVC中使用吗?我似乎能够正确地捕获异常,但无法停止它:每次我尝试呈现错误页面时都会发生相同的异常。 - Andy
此错误消息在到达控制器之前由IIS抛出。为了通知用户文件超过了最大上传限制(在您的web-config中设置),您可以通过JS直接验证文件大小,并使用onchange事件。例如:<input type="file" id="upload" name="upload" onchange="showFileSize();" />showFileSize()内,您可以通过var input = document.getElementById("upload"); var file = input.files[0];显示基于文件大小的错误消息并附加一个HTML标记。 - Alfred Wallace
16个回答

97

很遗憾没有简单的方法可以捕获这种异常。我的做法是要么在页面级别覆盖OnError方法,要么在global.asax中覆盖Application_Error方法,然后检查它是否是最大请求失败,如果是,则转到错误页面。

protected override void OnError(EventArgs e) .....


private void Application_Error(object sender, EventArgs e)
{
    if (GlobalHelper.IsMaxRequestExceededException(this.Server.GetLastError()))
    {
        this.Server.ClearError();
        this.Server.Transfer("~/error/UploadTooLarge.aspx");
    }
}

这并不是正式的解决方案,但以下代码对我有效

const int TimedOutExceptionCode = -2147467259;
public static bool IsMaxRequestExceededException(Exception e)
{
    // unhandled errors = caught at global.ascx level
    // http exception = caught at page level

    Exception main;
    var unhandled = e as HttpUnhandledException;

    if (unhandled != null && unhandled.ErrorCode == TimedOutExceptionCode)
    {
        main = unhandled.InnerException;
    }
    else
    {
        main = e;
    }


    var http = main as HttpException;

    if (http != null && http.ErrorCode == TimedOutExceptionCode)
    {
        // hack: no real method of identifying if the error is max request exceeded as 
        // it is treated as a timeout exception
        if (http.StackTrace.Contains("GetEntireRawContent"))
        {
            // MAX REQUEST HAS BEEN EXCEEDED
            return true;
        }
    }

    return false;
}

2
谢谢。OnError没有起作用,但是Application_Error有。我们实际上已经为此设置了一个处理程序,但是有人在代码中将其关闭了。 - Marcus L
14
@sam-rueby 我不想在一个可能因本地化而改变的字符串错误消息上进行回复。 - Damien McGivern
这个在我的MVC应用程序中起作用了,但只有在我将this.Server.Transfer更改为this.Response.Redirect之后才能正常运行。 - Mike Strother
@DamienMcGivern:我应该使用哪个命名空间来访问GlobalHelper方法?它给我一个“GlobalHelper在当前上下文中不存在”的错误。 - Sohail
4
针对 .NET 4.0 及更高版本,有更好的方法来判断是否超过了最大请求大小。您可以通过检查 HttpException 的条件来验证此情况:httpException.WebEventCode == WebEventCodes.RuntimeErrorPostTooLarge - 使用 System.Web.Management.WebEventCodes - mco
显示剩余7条评论

58

如GateKiller所说,您需要更改maxRequestLength。如果上传速度太慢,您可能还需要更改executionTimeout。请注意,您不希望这两个设置过大,否则您将容易受到DOS攻击。

executionTimeout的默认值为360秒或6分钟。

您可以使用httpRuntime Element更改maxRequestLength和executionTimeout。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.web>
        <httpRuntime maxRequestLength="102400" executionTimeout="1200" />
    </system.web>
</configuration>

编辑:

如果您想无论如何处理异常,那么就像已经提到的那样,您需要在Global.asax中处理它。这里是一个代码示例链接。


2
谢谢您的回复,但正如我在对GK答案的评论中所说,这并不能真正解决我的问题。这也不是超时问题,因为异常会立即抛出。我将编辑问题以更清楚地表达这一点。 - Marcus L
4
代码示例的网址指向一个无法访问的页面...有人能修复吗? - deostroll

20

您可以通过增加web.config文件中的最大请求长度来解决此问题:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.web>
        <httpRuntime maxRequestLength="102400" />
    </system.web>
</configuration>

上面的示例是为了100Mb的限制而设定的。


19
是的,也不是。你把限制提高了,但它实际上并没有处理异常情况。如果有人试图上传101+ Mb的文件,仍然会遇到相同的问题。限制应该确实为5 Mb。 - Marcus L

10
如果你想进行客户端验证,以便减少抛出异常的需求,你可以尝试实现客户端文件大小验证。
注意:这仅适用于支持HTML5的浏览器。 http://www.html5rocks.com/en/tutorials/file/dndfiles/
<form id="FormID" action="post" name="FormID">
    <input id="target" name="target" class="target" type="file" />
</form>

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js" type="text/javascript"></script>

<script type="text/javascript" language="javascript">

    $('.target').change(function () {

        if (typeof FileReader !== "undefined") {
            var size = document.getElementById('target').files[0].size;
            // check file size

            if (size > 100000) {

                $(this).val("");

            }
        }

    });

</script>


9

嗨,Damien McGivern提到的解决方案只适用于IIS6,

它在IIS7和ASP.NET开发服务器上无法运行。我看到“404-文件或目录未找到”页面。

有什么想法吗?

编辑:

明白了...这个解决方案仍然不适用于ASP.NET开发服务器,但我知道为什么在我的情况下它不能在IIS7上运行了。

原因是IIS7具有内置的请求扫描功能,强制实施上传文件大小限制,默认为30000000字节(略小于30MB)。

我试图上传100MB大小的文件以测试Damien McGivern提到的解决方案(web.config中的maxRequestLength =“10240”即10MB)。现在,如果我上传的文件大小大于10MB且小于30MB,则页面将重定向到指定的错误页面。但是,如果文件大小大于30MB,则会显示丑陋的内置错误页面,显示“404-文件或目录未找到”。

因此,为避免这种情况,您必须增加IIS7网站的最大允许请求内容长度。

可以使用以下命令来完成:

appcmd set config "SiteName" -section:requestFiltering -requestLimits.maxAllowedContentLength:209715200 -commitpath:apphost

我已将最大内容长度设置为200MB。
进行此设置后,当我尝试上传100MB的文件时,页面成功重定向到我的错误页面。
更多详细信息请参见:http://weblogs.asp.net/jgalloway/archive/2008/01/08/large-file-uploads-in-asp-net.aspx

抱歉!我已将我的查询作为答案添加,我不知道如何在现有帖子中添加评论。 - Vinod T. Patil
1
您需要更多的声望才能评论帖子。请查看常见问题解答以了解有关当前声望可以/不可以做什么的更多细节。 - slaphappy

8

这里有一种替代方式,不涉及任何“黑科技”,但需要ASP.NET 4.0或更高版本:

//Global.asax
private void Application_Error(object sender, EventArgs e)
{
    var ex = Server.GetLastError();
    var httpException = ex as HttpException ?? ex.InnerException as HttpException;
    if(httpException == null) return;

    if(httpException.WebEventCode == WebEventCodes.RuntimeErrorPostTooLarge)
    {
        //handle the error
        Response.Write("Sorry, file is too big"); //show this message for instance
    }
}

4

其中一种方法是在web.config中设置最大大小,如上面已经提到的:

<system.web>         
    <httpRuntime maxRequestLength="102400" />     
</system.web>

在处理上传事件时,检查文件大小,如果超过特定大小,则可以进行限制。

例如:
protected void btnUploadImage_OnClick(object sender, EventArgs e)
{
    if (fil.FileBytes.Length > 51200)
    {
         TextBoxMsg.Text = "file size must be less than 50KB";
    }
}

3
这行不通。点击事件从未触发。异常发生在之前。 - Lombas

3

在IIS 7及以上版本中:

web.config文件:

<system.webServer>
  <security >
    <requestFiltering>
      <requestLimits maxAllowedContentLength="[Size In Bytes]" />
    </requestFiltering>
  </security>
</system.webServer>

您可以在代码后端进行检查,像这样:
If FileUpload1.PostedFile.ContentLength > 2097152 Then ' (2097152 = 2 Mb)
  ' Exceeded the 2 Mb limit
  ' Do something
End If

请确保web.config中的[Size In Bytes]大于您要上传的文件大小,这样就不会发生404错误。然后您可以在代码后台使用ContentLength检查文件大小,这样会更好。


3

2

你可能已经知道了,最大请求长度在两个地方进行配置。

  1. maxRequestLength - 在 ASP.NET 应用程序层面进行控制
  2. maxAllowedContentLength - 在 <system.webServer> 下,在 IIS 层面进行控制

第一种情况已经被其他答案覆盖。

要捕捉第二种情况,你需要在 global.asax 中进行以下操作:

protected void Application_EndRequest(object sender, EventArgs e)
{
    //check for the "file is too big" exception if thrown at the IIS level
    if (Response.StatusCode == 404 && Response.SubStatusCode == 13)
    {
        Response.Write("Too big a file"); //just an example
        Response.End();
    }
}

较新版本的IIS中,StatusCode为413。 - Garr Godfrey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接