捕获“超出最大请求长度”

时间:2009-03-20 09:23:09

标签: c# asp.net httpexception

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

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

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

16 个答案:

答案 0 :(得分:95)

遗憾的是,没有简单的方法可以捕获这样的异常。我所做的是覆盖页面级别的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;
}

答案 1 :(得分: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中处理它。这是code example的链接。

答案 2 :(得分:20)

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

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

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

答案 3 :(得分:9)

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

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

有什么想法吗?

修改

知道了...这个解决方案仍然无法在ASP.NET Development Server上运行,但我得到了为什么在我的情况下它无法在IIS7上运行的原因。

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

我试图上传大小为100 MB的文件来测试Damien McGivern提到的解决方案(maxRequestLength =“10240”,即web.config中的10MB)。现在,如果我上传大小&gt;的文件10MB和<10MB 30 MB然后页面被重定向到指定的错误页面。但是如果文件大小是> 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了解详情。

答案 4 :(得分: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>

答案 5 :(得分:5)

执行此操作的一种方法是在web.config中设置最大大小,如上所述,例如

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

然后当您处理上传事件时,检查大小,如果超过特定数量,您可以捕获它 e.g。

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

答案 6 :(得分: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
    }
}

答案 7 :(得分:3)

答案 8 :(得分: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检查后面代码中的文件大小,这将更好

答案 9 :(得分:2)

您可能知道,最大请求长度是在两个位置配置的。

  1. maxRequestLength - 受ASP.NET应用级控制
  2. maxAllowedContentLength - 在<system.webServer>下,受IIS级控制
  3. 这个问题的其他答案涵盖了第一个案例。

    要抓住 THE SECOND ONE ,您需要在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();
        }
    }
    

答案 10 :(得分:1)

标记后

<security>
     <requestFiltering>
         <requestLimits maxAllowedContentLength="4500000" />
     </requestFiltering>
</security>

添加以下标记

 <httpErrors errorMode="Custom" existingResponse="Replace">
  <remove statusCode="404" subStatusCode="13" />
  <error statusCode="404" subStatusCode="13" prefixLanguageFilePath="" path="http://localhost/ErrorPage.aspx" responseMode="Redirect" />
</httpErrors>

您可以将网址添加到错误页面...

答案 11 :(得分:0)

您可以通过在web.config中增加最大请求长度和执行时间来解决此问题:

-Please澄清最大执行时间,然后是1200

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

答案 12 :(得分:0)

如何在EndRequest事件中捕获它?

protected void Application_EndRequest(object sender, EventArgs e)
    {
        HttpRequest request = HttpContext.Current.Request;
        HttpResponse response = HttpContext.Current.Response;
        if ((request.HttpMethod == "POST") &&
            (response.StatusCode == 404 && response.SubStatusCode == 13))
        {
            // Clear the response header but do not clear errors and
            // transfer back to requesting page to handle error
            response.ClearHeaders();
            HttpContext.Current.Server.Transfer(request.AppRelativeCurrentExecutionFilePath);
        }
    }

答案 13 :(得分:0)

可以通过以下方式进行检查:

        var httpException = ex as HttpException;
        if (httpException != null)
        {
            if (httpException.WebEventCode == System.Web.Management.WebEventCodes.RuntimeErrorPostTooLarge)
            {
                // Request too large

                return;

            }
        }

答案 14 :(得分:0)

我正在使用FileUpload控件和客户端脚本来检查文件大小。
HTML(请注意OnClientClick-在OnClick之前执行):

<asp:FileUpload ID="FileUploader" runat="server" />
<br />
<asp:Button ID="btnUpload" Text="Upload" runat="server" OnClientClick="return checkFileSize()" OnClick="UploadFile" />
<br />
<asp:Label ID="lblMessage" runat="server" CssClass="lblMessage"></asp:Label>

然后编写脚本(如果大小太大,请注意“ return false”:这是为了取消OnClick):

function checkFileSize() 
{
    var input = document.getElementById("FileUploader");
    var lbl = document.getElementById("lblMessage");
    if (input.files[0].size < 4194304)
    {
        lbl.className = "lblMessage";
        lbl.innerText = "File was uploaded";
    }
    else
    {
        lbl.className = "lblError";
        lbl.innerText = "Your file cannot be uploaded because it is too big (4 MB max.)";
        return false;
    }
}

答案 15 :(得分:0)

在 Martin van Bergeijk 的回答之后,我添加了一个额外的 if 块来检查他们在提交之前是否真的选择了一个文件。

if(input.files[0] == null)
{lbl.innertext = "You must select a file before selecting Submit"}
return false;