web-dev-qa-db-fra.com

Capture "Longueur maximale de la demande dépassée"

J'écris une fonction de téléchargement et j'ai des problèmes pour intercepter "System.Web.HttpException: longueur maximale de la demande dépassée" avec des fichiers plus volumineux que la taille maximale spécifiée dans httpRuntimein web.config (taille maximale définie sur 5120). J'utilise un simple <input> pour le fichier.

Le problème est que l'exception est levée avant l'événement click du bouton de téléchargement et qu'elle survient avant que mon code ne soit exécuté. Alors, comment puis-je attraper et gérer l'exception?

EDIT: L'exception est levée instantanément, je suis donc presque sûr que ce n'est pas un problème de délai d'attente en raison de connexions lentes.

109
Marcus L

Malheureusement, il n’ya pas de moyen facile d’attraper une telle exception. Ce que je fais est soit remplacer la méthode OnError au niveau de la page ou le Application_Error dans global.asax, puis vérifiez si c'était un échec Max Request et, le cas échéant, le transfert à une page d'erreur.

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

C'est un hack mais le code ci-dessous fonctionne pour moi

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;
}
96
Damien McGivern

Comme GateKiller l'a dit, vous devez changer maxRequestLength. Vous devrez peut-être également modifier la valeur executionTimeout si la vitesse de téléchargement est trop lente. Notez que vous ne voulez pas que ces paramètres soient trop gros, sinon vous serez ouvert aux attaques DOS.

La valeur par défaut pour executionTimeout est 360 secondes ou 6 minutes.

Vous pouvez modifier maxRequestLength et executionTimeout avec httpRuntime Element .

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

MODIFIER:

Si vous voulez gérer l'exception malgré tout, comme il a déjà été dit, vous devez la gérer dans Global.asax. Voici un lien vers un exemple de code .

58
Jonathan Parker

Vous pouvez résoudre ce problème en augmentant la longueur maximale de la demande dans votre web.config:

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

L'exemple ci-dessus concerne une limite de 100 Mo.

20
GateKiller

Si vous souhaitez également une validation côté client afin que vous ayez moins besoin de lever des exceptions, vous pouvez essayer d'implémenter la validation de la taille du fichier côté client.

Remarque: cela ne fonctionne que dans les navigateurs prenant en charge 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>
9
Andrew

Salut solution mentionné par Damien McGivern, Fonctionne sur IIS6 uniquement,

Cela ne fonctionne pas sur IIS7 et ASP.NET Development Server. La page affiche "404 - Fichier ou répertoire introuvable."

Des idées?

EDIT:

Compris ... Cette solution ne fonctionne toujours pas sur ASP.NET Development Server, mais j'ai eu la raison pour laquelle elle ne fonctionnait pas sur IIS7 dans mon cas.

La raison en est que IIS7 a une analyse de requête intégrée qui impose une limite de fichier de téléchargement qui est définie par défaut sur 30000000 octets (ce qui représente un peu moins de 30 Mo).

Et j’essayais de télécharger un fichier de taille 100 Mo pour tester la solution mentionnée par Damien McGivern (avec maxRequestLength = "10240", c’est-à-dire 10 Mo dans web.config). Maintenant, si je télécharge le fichier de taille> 10 Mo et <30 Mo, la page est redirigée vers la page d'erreur spécifiée. Mais si la taille du fichier est supérieure à 30 Mo, la page d'erreur intégrée laide et affichant "404 - Fichier ou répertoire non trouvé" s'affiche.

Donc, pour éviter cela, vous devez augmenter le maximum. autorisé la longueur du contenu de la demande pour votre site Web dans IIS7. Cela peut être fait en utilisant la commande suivante,

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

J'ai réglé le max. longueur du contenu à 200 Mo.

Après avoir effectué ce réglage, la page est correctement redirigée vers ma page d'erreur lorsque j'essaie de télécharger un fichier de 100 Mo

Référez-vous, http://weblogs.asp.net/jgalloway/archive/2008/01/08/large-file-uploads-in-asp-net.aspx pour plus de détails.

9
Vinod T. Patil

Voici une autre solution, qui n'implique aucun "hacks", mais nécessite ASP.NET 4.0 ou version ultérieure:

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

Une façon de procéder consiste à définir la taille maximale dans web.config, comme indiqué précédemment, par ex.

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

puis, lorsque vous gérez l'événement de téléchargement, vérifiez sa taille et si son montant dépasse un certain montant, vous pouvez le piéger, par exemple.

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

Dans IIS 7 et au-delà:

fichier web.config:

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

Vous pouvez ensuite vérifier le code derrière, comme suit:

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

Assurez-vous simplement que [Taille en octets] dans le fichier web.config est supérieur à la taille du fichier que vous souhaitez télécharger, vous ne recevrez donc pas l'erreur 404. Vous pouvez ensuite vérifier la taille du fichier dans le code après en utilisant ContentLength qui serait bien mieux

3
user3767204

Comme vous le savez probablement, la longueur maximale de la demande est configurée dans DEUX places.

  1. maxRequestLength - contrôlé au niveau de l'application ASP.NET
  2. maxAllowedContentLength - sous <system.webServer>, contrôlé au niveau IIS

Le premier cas est couvert par d'autres réponses à cette question.

Pour attraper LA SECONDE vous devez le faire dans 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();
    }
}
2
jazzcat

Après tag

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

ajouter la balise suivante

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

vous pouvez ajouter l'URL à la page d'erreur ...

1
Diego

Que diriez-vous d'attraper l'événement 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);
        }
    }
0
Khoa Tran

Il peut être vérifié via:

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

                return;

            }
        }
0
Raghav

Vous pouvez résoudre ce problème en augmentant la longueur maximale de la requête et le délai d’exécution dans votre fichier web.config:

-Veuillez clarifier le délai d’exécution maximum, puis 1200

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