捕捉“超过最大请求长度”

我正在写一个上传函数,有问题捕捉“系统。韦伯。如果文件大于 web.config 中指定的最大大小(最大大小设置为5120) ,则 HttpException: 最大请求长度超过”。我使用一个简单的 <input>文件。

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

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

149537 次浏览

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

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

上面的例子是一个100Mb 的限制。

正如“门户杀手”所说,您需要更改 maxRequestLlength。如果上传速度太慢,您可能还需要更改 ExectionTimeout。请注意,您不希望这些设置中的任何一个太大,否则您将受到 DOS 攻击。

ExectionTimeout 的默认值是360秒或6分钟。

You can change the maxRequestLength and executionTimeout with the httpRuntime Element.

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

编辑:

如果您想处理异常,那么如前所述,您需要在 Global.asax 中处理它。这是 代码示例的链接。

不幸的是,没有简单的方法来捕捉这种异常。我所做的是在页面级别覆盖 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");
}
}

It's a hack but the code below works for me

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

你好,达米恩 · 麦吉文提到的解决方案, 只能在 IIS6上运行,

它不能在 IIS7和 ASP.NET 开发服务器上工作。我得到的页面显示“404-文件或目录未找到。”

Any ideas?

EDIT:

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

The reason is IIS7 has a built-in request scanning which imposes an upload file cap which defaults to 30000000 bytes (which is slightly less that 30MB).

我尝试上传大小为100MB 的文件来测试 Damien McGivern 提到的解决方案(在 web.config 中使用 maxRequestLlength = “10240”即10MB)。现在,如果我上传大小 > 10 MB 和 < 30 MB 的文件,那么页面将被重定向到指定的错误页面。但是如果文件大小 > 30MB,那么它会显示丑陋的内置错误页面,显示“404-File or directory not found”

So, to avoid this, you have to increase the max. allowed request content length for your website in IIS7. 可以使用以下命令完成,

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

我已经将 max. content 长度设置为200MB。

完成此设置后,当我尝试上传100MB 的文件时,页面被成功地重定向到我的错误页面

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

如果您也想要客户端验证,这样就不需要抛出异常,那么您可以尝试实现客户端文件大小验证。

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

一种方法是在 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";
}
}

在 IIS 7及以后:

web.config file:

<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错误。然后您可以使用 ContentLlength 检查代码中的文件大小,这样会好得多

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

-Please Clarify the maximum execution time out grater then 1200

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

这里有一个替代方法,不涉及任何“黑客”,但需要 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
}
}

追踪之后

<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 添加到错误页面..。

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

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

  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();
}
}

可以通过以下途径进行检查:

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


return;


}
}

我使用 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>

Then the script (note the 'return false' if the size is too big: this is to cancel the 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;
}
}

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

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