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

Posted

技术标签:

【中文标题】捕获“超出最大请求长度”【英文标题】:Catching "Maximum request length exceeded" 【发布时间】:2009-03-20 09:23:08 【问题描述】:

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

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

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

【问题讨论】:

有人用 MVC 试过这个吗?我似乎能够以正确的方式捕获异常,但我无法阻止它:每次我尝试呈现错误页面时都会发生相同的异常。 此错误消息由 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 标记。 【参考方案1】:

不幸的是,没有简单的方法来捕获此类异常。我所做的是要么覆盖页面级别的 OnError 方法,要么覆盖 global.asax 中的 Application_Error,然后检查它是否是 Max Request 失败,如果是,则转移到错误页面。

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");
    

这是一个 hack,但下面的代码对我有用

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;

【讨论】:

谢谢。 OnError 不起作用,但 Application_Error 起作用了。我们实际上有一个处理程序,但有人在代码中将其关闭。 两年前的事了,但我还是想问一下现在还可以吗? 'GetEntireRawContent' 的字符串比较工作正常吗?我认为这不是超时问题。有没有人站出来指出我在这方面的某处阴天? @Elaine 是的,这种技术仍然适用于 ASP.Net 4.0。如果您尝试上传大于最大请求长度的请求,ASP.Net 会抛出带有超时代码的 HttpException。使用反射器查看 System.Web.HttpRequest.GetEntireRawContent()。 @sam-rueby 我不想回复可能因本地化而改变的字符串错误消息。 对于 .NET 4.0 及更高版本,有更好的方法来识别是否超过了最大请求大小。您可以检查 HttpException 的这种情况:httpException.WebEventCode == WebEventCodes.RuntimeErrorPostTooLarge - 使用 System.Web.Management.WebEventCodes【参考方案2】:

正如 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的链接。

【讨论】:

感谢您的回复,但正如我在对 GK 回答的评论中所说,这并不能真正解决我的问题。这也不是超时问题,因为异常会立即抛出。我将编辑问题以使其更清楚。 代码示例 url 指向的页面不可用...谁能解决这个问题?【参考方案3】:

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

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

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

【讨论】:

是的,也不是。您进一步推动了限制,但它并没有真正处理异常。如果有人尝试上传 101+ Mb,您仍然会遇到同样的问题。限制确实需要为 5 Mb。【参考方案4】:

如果您还想要客户端验证,从而减少抛出异常的需要,您可以尝试实现客户端文件大小验证。

注意:这只适用于支持 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】:

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

它不适用于 IIS7 和 ASP.NET 开发服务器。我的页面显示“404 - 找不到文件或目录。”

有什么想法吗?

编辑:

知道了...这个解决方案仍然无法在 ASP.NET 开发服务器上运行,但我知道它在我的情况下无法在 IIS7 上运行的原因。

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

我试图上传大小为 100 MB 的文件来测试 Damien McGivern 提到的解决方案(maxRequestLength="10240",即 web.config 中的 10MB)。现在,如果我上传大小 > 10MB 且 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。

【讨论】:

对不起!我已将我的查询添加为答案,我不知道如何将 cmets 添加到现有帖子中。 你只需要更多的代表。评论帖子。请参阅常见问题解答,了解有关您当前代表可以/不能做什么的更多详细信息。【参考方案6】:

这是另一种方法,不涉及任何“黑客”,但需要 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】:

这样做的一种方法是在 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";
    

【讨论】:

这不起作用。永远不会触发点击事件。异常发生在之前。【参考方案8】:

适用于 IIS7 及更高版本的解决方案:Display custom error page when file upload exceeds allowed size in ASP.NET MVC

【讨论】:

【参考方案9】:

在 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 在后面的代码中检查文件大小,这会更好

【讨论】:

【参考方案10】:

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

    maxRequestLength - 在 ASP.NET 应用级别控制 maxAllowedContentLength - 在&lt;system.webServer&gt; 下,在 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 的状态码为 413【参考方案11】:

我正在使用 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;
    

【讨论】:

【参考方案12】:

标签之后

<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>

你可以将Url添加到错误页面...

【讨论】:

【参考方案13】:

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

-请说明最大执行超时时间大于 1200

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

【讨论】:

【参考方案14】:

在 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);
        
    

【讨论】:

IIS 8 现在将 StatusCode 设置为 413【参考方案15】:

可以通过以下方式检查:

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

                return;

            
        

【讨论】:

【参考方案16】:

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

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

【讨论】:

以上是关于捕获“超出最大请求长度”的主要内容,如果未能解决你的问题,请参考以下文章

uSQL 超出最大请求长度

如何解决“超出最大请求长度”异常?

在大型数据网格中分页时“超出最大请求长度”[重复]

IIS 6“超出最大请求长度。”在 Global.asax 之前触发 [重复]

WebApi 2 超出最大请求长度

s-s-rS 上传 14Mb 报告不起作用(超出最大请求长度。)