アップロード関数を作成しているときに、httpRuntime
in web.configで指定された最大サイズ(5120に設定された最大サイズ)を超えるファイルで「System.Web.HttpException:Maximum request length exceeded」をキャッチする問題があります。ファイルに単純な<input>
を使用しています。
問題は、アップロードボタンのクリックイベントの前に例外がスローされ、コードが実行される前に例外が発生することです。それでは、どのように例外をキャッチして処理しますか?
EDIT:例外は即座にスローされるため、接続が遅いためにタイムアウトの問題が発生することはないと確信しています。
残念ながら、そのような例外をキャッチする簡単な方法はありません。私がしていることは、ページレベルで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");
}
}
それはハックですが、以下のコードは私のために機能します
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;
}
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で例外を処理する必要があります。 コード例 へのリンクです。
これを解決するには、web.configの最大リクエスト長を増やします。
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<httpRuntime maxRequestLength="102400" />
</system.web>
</configuration>
上記の例は100Mbの制限です。
クライアント側の検証も必要な場合は、例外をスローする必要が少なくなるため、クライアント側のファイルサイズ検証を実装してみてください。
注:これは、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>
こんにちは、Damien McGivernが言及したソリューション、IIS6のみで動作、
IIS7およびASP.NET開発サーバーでは機能しません。 「404-ファイルまたはディレクトリが見つかりません」と表示されるページが表示されます。
何か案は?
編集:
わかった...このソリューションはASP.NET開発サーバーではまだ動作しませんが、私の場合はIIS7で動作しなかった理由がわかりました。
その理由は、IIS7には、デフォルトで30000000バイト(30 MB未満)のアップロードファイルキャップを課すビルトインリクエストスキャンがあるためです。
そして、Damien McGivernが言及したソリューション(maxRequestLength = "10240"、つまりweb.configで10MB)をテストするために、サイズ100 MBのファイルをアップロードしようとしました。ここで、サイズが10 MBを超え30 MB未満のファイルをアップロードすると、ページは指定されたエラーページにリダイレクトされます。ただし、ファイルサイズが30 MBを超える場合、「404-File or directory not found。」と表示されるい組み込みエラーページが表示されます。
そのため、これを回避するには、最大値を増やす必要があります。 IIS7でWebサイトのリクエストコンテンツの長さを許可しました。これは、次のコマンドを使用して実行できます。
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 を参照してください。
「ハッキング」を伴わないが、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
}
}
これを行う1つの方法は、上記で既に述べたように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";
}
}
IIS7以降で動作するソリューション: ファイルのアップロードがASP.NET MVCで許可されたサイズを超えたときにカスタムエラーページを表示する
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を使用して、コードビハインドでファイルサイズを確認できます。
おそらくご存知のとおり、最大リクエスト長はTWOの場所で設定されます。
maxRequestLength
-ASP.NETアプリレベルで制御maxAllowedContentLength
-IISレベルで制御される<system.webServer>
の下最初のケースは、この質問に対する他の回答でカバーされています。
セカンドワンをキャッチするには、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();
}
}
タグの後
<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);
}
}
次の方法で確認できます。
var httpException = ex as HttpException;
if (httpException != null)
{
if (httpException.WebEventCode == System.Web.Management.WebEventCodes.RuntimeErrorPostTooLarge)
{
// Request too large
return;
}
}
Web.configで最大リクエストの長さと実行タイムアウトを増やすことでこれを解決できます:
-最大実行タイムアウトが1200を超えていることを明確にしてください
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.web> <httpRuntime maxRequestLength="102400" executionTimeout="1200" /> </system.web> </configuration>