Catching "Maximale Anforderungslänge überschritten"

112

Ich schreibe eine Upload-Funktion und habe Probleme beim Abfangen von "System.Web.HttpException: Maximale Anforderungslänge überschritten" mit Dateien, die größer als die httpRuntimein web.config angegebene maximale Größe sind (maximale Größe auf 5120 festgelegt). Ich benutze eine einfache <input>für die Datei.

Das Problem ist, dass die Ausnahme vor dem Klickereignis der Upload-Schaltfläche ausgelöst wird und die Ausnahme auftritt, bevor mein Code ausgeführt wird. Wie kann ich die Ausnahme abfangen und behandeln?

BEARBEITEN: Die Ausnahme wird sofort ausgelöst, daher bin ich mir ziemlich sicher, dass es sich aufgrund langsamer Verbindungen nicht um ein Timeout-Problem handelt.

Marcus L.
quelle
5
Hat jemand dies mit MVC versucht? Ich scheine in der Lage zu sein, die Ausnahme auf die richtige Weise abzufangen, aber ich kann sie nicht stoppen: Jedes Mal, wenn ich versuche, eine Fehlerseite zu rendern, tritt dieselbe Ausnahme auf.
Andy
Diese Fehlermeldung wird von IIS ausgegeben, bevor der Controller erreicht wird. Um den Benutzer zu benachrichtigen, dass die Datei das in Ihrer Webkonfiguration festgelegte maximale Upload-Limit überschreitet, können Sie die Dateigröße direkt über JS mit einem Onchange-Ereignis überprüfen. Zum Beispiel können Sie <input type="file" id="upload" name="upload" onchange="showFileSize();" />Inside showFileSize()eine Fehlermeldung basierend auf Ihrer Dateigröße über var input = document.getElementById("upload"); var file = input.files[0];ein HTML-Tag anzeigen und anhängen.
Alfred Wallace

Antworten:

97

Es gibt leider keine einfache Möglichkeit, eine solche Ausnahme zu erwischen. Ich überschreibe entweder die OnError-Methode auf Seitenebene oder den Application_Error in global.asax, überprüfe dann, ob es sich um einen Max Request-Fehler handelt, und übertrage ihn in diesem Fall auf eine Fehlerseite.

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

Es ist ein Hack, aber der folgende Code funktioniert für mich

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;
}
Damien McGivern
quelle
2
Vielen Dank. OnError hat nicht funktioniert, Application_Error jedoch. Wir haben tatsächlich einen Handler dafür, aber jemand hatte ihn im Code deaktiviert.
Marcus L
noch vor zwei Jahren, aber ich möchte immer noch fragen, ob das bis jetzt gut funktioniert hat? Funktioniert der Zeichenfolgenvergleich von 'GetEntireRawContent' einwandfrei? Ich denke nicht, dass dies ein Timeout-Problem ist. Gibt es jemanden, der mich darauf hinweist, dass ich diesbezüglich irgendwo unklug bin?
Elaine
@Elaine Ja, diese Technik funktioniert immer noch mit ASP.Net 4.0. Wenn Sie versuchen, eine Anforderung hochzuladen, die größer als die maximale Anforderungslänge ist, löst ASP.Net eine HttpException mit dem Timeout-Code aus. Schauen Sie in System.Web.HttpRequest.GetEntireRawContent () mit Reflektor nach.
Damien McGivern
12
@ sam-rueby Ich wollte nicht auf eine String-Fehlermeldung antworten, die sich aufgrund der Lokalisierung ändern könnte.
Damien McGivern
4
Für .NET 4.0 und höher gibt es eine bessere Möglichkeit, festzustellen, ob die maximale Anforderungsgröße überschritten wurde. Sie können diese Bedingung für HttpException überprüfen: httpException.WebEventCode == WebEventCodes.RuntimeErrorPostTooLarge- mit System.Web.Management.WebEventCodes
mco
58

Wie GateKiller sagte, müssen Sie die maxRequestLength ändern. Möglicherweise müssen Sie auch das ExecutionTimeout ändern, falls die Upload-Geschwindigkeit zu langsam ist. Beachten Sie, dass keine dieser Einstellungen zu groß sein soll, da Sie sonst für DOS-Angriffe offen sind.

Der Standardwert für das ExecutionTimeout ist 360 Sekunden oder 6 Minuten.

Sie können die maxRequestLength und das ExecutionTimeout mit dem httpRuntime-Element ändern .

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

BEARBEITEN:

Wenn Sie die Ausnahme trotzdem behandeln möchten, müssen Sie sie, wie bereits erwähnt, in Global.asax behandeln. Hier ist ein Link zu einem Codebeispiel .

Jonathan Parker
quelle
2
Vielen Dank für Ihre Antwort, aber wie ich in meinem Kommentar zu GKs Antwort sagte, löst dies mein Problem nicht wirklich. Es ist auch kein Timeout-Problem, da die Ausnahme sofort ausgelöst wird. Ich werde die Frage bearbeiten, um das klarer zu machen.
Marcus L
4
Die Codebeispiel-URL verweist auf eine Seite, die nicht verfügbar ist. Kann jemand dies beheben?
Deostroll
20

Sie können dies lösen, indem Sie die maximale Anforderungslänge in Ihrer web.config erhöhen:

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

Das obige Beispiel gilt für ein Limit von 100 MB.

GateKiller
quelle
18
Ja und nein. Sie verschieben das Limit weiter, aber die Ausnahme wird nicht wirklich behandelt. Sie werden immer noch das gleiche Problem bekommen, wenn jemand versucht, mehr als 101 MB hochzuladen. Das Limit muss wirklich 5 MB betragen.
Marcus L
10

Wenn Sie auch eine clientseitige Validierung wünschen, damit Sie weniger Ausnahmen auslösen müssen, können Sie versuchen, eine clientseitige Validierung der Dateigröße zu implementieren.

Hinweis: Dies funktioniert nur in Browsern, die HTML5 unterstützen. http://www.html5rocks.com/de/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>

Andrew
quelle
9

Hallo Lösung von Damien McGivern erwähnt, funktioniert nur auf IIS6,

Es funktioniert nicht unter IIS7 und ASP.NET Development Server. Auf der Seite wird "404 - Datei oder Verzeichnis nicht gefunden" angezeigt.

Irgendwelche Ideen?

BEARBEITEN:

Verstanden ... Diese Lösung funktioniert immer noch nicht auf ASP.NET Development Server, aber ich habe den Grund, warum sie in meinem Fall nicht auf IIS7 funktioniert hat.

Der Grund dafür ist, dass in IIS7 ein Anforderungsscan integriert ist, der eine Obergrenze für die Upload-Datei auferlegt, die standardmäßig 30000000 Byte (etwas weniger als 30 MB) beträgt.

Und ich habe versucht, eine Datei mit einer Größe von 100 MB hochzuladen, um die von Damien McGivern erwähnte Lösung zu testen (mit maxRequestLength = "10240", dh 10 MB in web.config). Wenn ich jetzt eine Datei mit einer Größe von> 10 MB und <30 MB hochlade, wird die Seite auf die angegebene Fehlerseite umgeleitet. Wenn die Dateigröße jedoch> 30 MB ist, wird auf der hässlichen integrierten Fehlerseite "404 - Datei oder Verzeichnis nicht gefunden" angezeigt.

Um dies zu vermeiden, müssen Sie die max. Zulässige Länge des Anforderungsinhalts für Ihre Website in IIS7. Dies kann mit dem folgenden Befehl erfolgen:

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

Ich habe die max eingestellt. Inhaltslänge bis 200 MB.

Nach dieser Einstellung wird die Seite erfolgreich auf meine Fehlerseite umgeleitet, wenn ich versuche, eine Datei mit 100 MB hochzuladen

Weitere Informationen finden Sie unter http://weblogs.asp.net/jgalloway/archive/2008/01/08/large-file-uploads-in-asp-net.aspx .

Vinod T. Patil
quelle
Es tut uns leid! Ich habe meine Anfrage als Antwort hinzugefügt. Ich weiß nicht, wie ich Kommentare zu vorhandenen Posts hinzufügen soll.
Vinod T. Patil
1
Sie brauchen nur mehr Wiederholungen. Beiträge kommentieren. In der FAQ finden Sie weitere Informationen darüber, was Sie mit Ihrem aktuellen Mitarbeiter tun können / nicht.
Slaphappy
7

Hier ist eine alternative Methode, die keine "Hacks" beinhaltet, sondern ASP.NET 4.0 oder höher erfordert:

//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
    }
}
Serge Shultz
quelle
4

Eine Möglichkeit, dies zu tun, besteht darin, die maximale Größe in web.config festzulegen, wie oben bereits angegeben, z

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

Wenn Sie dann das Upload-Ereignis behandeln, überprüfen Sie die Größe. Wenn es über einem bestimmten Betrag liegt, können Sie es abfangen, z

protected void btnUploadImage_OnClick(object sender, EventArgs e)
{
    if (fil.FileBytes.Length > 51200)
    {
         TextBoxMsg.Text = "file size must be less than 50KB";
    }
}
BaggieBoy
quelle
1
Das funktioniert nicht. Das Klickereignis wird niemals ausgelöst. Die Ausnahme tritt vorher auf.
Lombas
3

In IIS 7 und darüber hinaus:

Datei web.config:

<system.webServer>
  <security >
    <requestFiltering>
      <requestLimits maxAllowedContentLength="[Size In Bytes]" />
    </requestFiltering>
  </security>
</system.webServer>

Sie können dann den Code dahinter wie folgt einchecken:

If FileUpload1.PostedFile.ContentLength > 2097152 Then ' (2097152 = 2 Mb)
  ' Exceeded the 2 Mb limit
  ' Do something
End If

Stellen Sie einfach sicher, dass die [Größe in Bytes] in der web.config größer ist als die Größe der Datei, die Sie hochladen möchten. Andernfalls wird der Fehler 404 nicht angezeigt. Sie können dann die Dateigröße im Code hinter der ContentLength überprüfen, was viel besser wäre

Walery Strauch
quelle
2

Wie Sie wahrscheinlich wissen, wird die maximale Anforderungslänge an ZWEI Stellen konfiguriert .

  1. maxRequestLength - Auf ASP.NET-App-Ebene gesteuert
  2. maxAllowedContentLength- unter <system.webServer>, auf IIS-Ebene kontrolliert

Der erste Fall wird durch andere Antworten auf diese Frage abgedeckt.

Um THE SECOND ONE zu fangen , müssen Sie dies in global.asax tun:

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

Nach dem Tag

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

Fügen Sie das folgende Tag hinzu

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

Sie können die URL zur Fehlerseite hinzufügen ...

Diego
quelle
0

Sie können dies lösen, indem Sie die maximale Anforderungslänge und Ausführungszeit in Ihrer web.config erhöhen:

-Bitte klären Sie die maximale Ausführungszeit von mehr als 1200

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

Wie wäre es mit einem EndRequest-Event?

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);
        }
    }
Khoa Tran
quelle
0

Es kann überprüft werden über:

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

                return;

            }
        }
Raghav
quelle