捕获"超出最大请求长度"

Mar*_*s L 110 c# asp.net httpexception

我正在编写一个上传函数,并且httpRuntime在web.config中使用大于指定最大大小的文件时捕获"System.Web.HttpException:超出最大请求长度"时遇到问题(最大大小设置为5120).我正在使用一个简单<input>的文件.

问题是在上传按钮的click-event之前抛出了异常,并且异常发生在我的代码运行之前.那么如何捕获和处理异常呢?

编辑:异常立即抛出,所以我很确定它不是由于连接速度慢导致的超时问题.

Dam*_*ern 96

不幸的是,没有简单的方法来捕获这样的例外.我所做的是覆盖页面级别的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");
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个黑客,但下面的代码适合我

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;
}
Run Code Online (Sandbox Code Playgroud)

  • @sam-rueby我不想回复因本地化而可能改变的字符串错误消息. (12认同)
  • 对于.NET 4.0及更高版本,有更好的方法来确定是否超出了最大请求大小.您可以检查此条件是否存在HttpException:`httpException.WebEventCode == WebEventCodes.RuntimeErrorPostTooLarge` - 使用System.Web.Management.WebEventCodes (3认同)
  • 谢谢.OnError不起作用,但Application_Error确实有效.我们实际上有一个处理程序,但有人在代码中关闭它. (2认同)

Jon*_*ker 58

正如GateKiller所说,你需要改变maxRequestLength.如果上传速度太慢,您可能还需要更改executionTimeout.请注意,您不希望这些设置中的任何一个太大,否则您将对DOS攻击开放.

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

您可以使用httpRuntime元素更改maxRequestLength和executionTimeout .

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.web>
        <httpRuntime maxRequestLength="102400" executionTimeout="1200" />
    </system.web>
</configuration>
Run Code Online (Sandbox Code Playgroud)

编辑:

如果你想要处理异常,那么就像已经说明的那样,你需要在Global.asax中处理它.这是代码示例的链接.

  • 代码示例url指向一个不可用的页面...任何人都可以修复此问题吗? (4认同)
  • 感谢您的回复,但正如我在对GK的回答中所说的那样,这并没有真正解决我的问题.它也不是超时问题,因为异常立即被抛出.我将编辑问题以使其更清晰. (2认同)

Gat*_*ler 20

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

<?xml version="1.0" encoding="utf-8"?>
<configuration>
    <system.web>
        <httpRuntime maxRequestLength="102400" />
    </system.web>
</configuration>
Run Code Online (Sandbox Code Playgroud)

上面的示例是针对100Mb的限制.

  • 是的,不.你进一步推动了限制,但它并没有真正处理异常.如果有人试图上传101+ Mb,你仍然会遇到同样的问题.限制确实需要5 Mb. (17认同)

Vin*_*til 9

Damien McGivern提到的解决方案,仅限IIS6上的Works,

它不适用于IIS7和ASP.NET Development Server.我得到的页面显示"404 - 找不到文件或目录".

有任何想法吗?

编辑:

得到它...这个解决方案仍然无法在ASP.NET Development Server上运行,但我得到了它在我的情况下不能在IIS7上工作的原因.

原因是IIS7有一个内置的请求扫描,它强加一个上传文件上限,默认为30000000字节(略小于30MB).

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

所以,要避免这种情况,你必须增加最大值.允许IIS7中的网站请求内容长度.这可以使用以下命令完成,

appcmd set config "SiteName" -section:requestFiltering -requestLimits.maxAllowedContentLength:209715200 -commitpath:apphost
Run Code Online (Sandbox Code Playgroud)

我设定了最大值.内容长度为200MB.

执行此设置后,当我尝试上传100MB的文件时,页面被无意中重定向到我的错误页面

有关详细信息,请参阅http://weblogs.asp.net/jgalloway/archive/2008/01/08/large-file-uploads-in-asp-net.aspx.


And*_*rew 9

如果您还希望进行客户端验证,那么您不需要抛出异常就可以尝试实现客户端文件大小验证.

注意:这仅适用于支持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>
Run Code Online (Sandbox Code Playgroud)


Ser*_*ltz 5

这是另一种方法,不涉及任何"黑客",但需要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
    }
}
Run Code Online (Sandbox Code Playgroud)