Recupero di "Lunghezza massima richiesta superata"


112

Sto scrivendo una funzione di caricamento e ho problemi a rilevare "System.Web.HttpException: Lunghezza massima richiesta superata" con file più grandi della dimensione massima specificata httpRuntimein web.config (dimensione massima impostata su 5120). Sto usando un semplice <input>per il file.

Il problema è che l'eccezione viene generata prima dell'evento clic del pulsante di caricamento e l'eccezione si verifica prima che il mio codice venga eseguito. Quindi come prendo e gestisco l'eccezione?

EDIT: l'eccezione viene generata istantaneamente, quindi sono abbastanza sicuro che non sia un problema di timeout a causa delle connessioni lente.


5
Qualcuno l'ha provato con MVC? Mi sembra di essere in grado di catturare l'eccezione nel modo giusto, ma non riesco a fermarla: ogni volta che provo a rendere una pagina di errore si verifica la stessa eccezione.
Andy

Questo messaggio di errore viene generato da IIS prima di raggiungere il controller. Per notificare all'utente che il file supera il limite massimo di caricamento (impostato nella configurazione web), è possibile convalidare direttamente la dimensione del file tramite JS con un evento onchange. Ad esempio <input type="file" id="upload" name="upload" onchange="showFileSize();" />Inside showFileSize(), è possibile visualizzare un messaggio di errore basato sulla dimensione del file tramite var input = document.getElementById("upload"); var file = input.files[0];e aggiungere un tag html.
Alfred Wallace

Risposte:


97

Sfortunatamente, non esiste un modo semplice per catturare tale eccezione. Quello che faccio è sovrascrivere il metodo OnError a livello di pagina o Application_Error in global.asax, quindi controllare se si è trattato di un errore di Max Request e, in tal caso, trasferirlo a una pagina di errore.

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

È un trucco ma il codice qui sotto funziona per 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;
}

2
Grazie. OnError non ha funzionato, ma Application_Error ha funzionato. In realtà abbiamo un gestore per questo, ma qualcuno lo aveva disattivato nel codice.
Marcus L

anche due anni fa, ma voglio ancora chiederti se ha funzionato bene fino ad ora? funziona bene il confronto delle stringhe di "GetEntireRawContent"? Non penso che questo sia un problema di timeout. c'è qualcuno che si è distinto per avermi segnalato un posto non nuvoloso riguardo a questo?
Elaine

@Elaine sì, questa tecnica funziona ancora con ASP.Net 4.0. Se si tenta di caricare una richiesta che è maggiore della lunghezza massima della richiesta, ASP.Net genera una HttpException con il codice di timeout. Dai un'occhiata a System.Web.HttpRequest.GetEntireRawContent () usando il riflettore.
Damien McGivern

12
@ sam-rueby Non volevo rispondere a un messaggio di errore di stringa che potrebbe cambiare a causa della localizzazione.
Damien McGivern

4
Per .NET 4.0 e versioni successive esiste un modo migliore per identificare se la dimensione massima della richiesta è stata superata. Puoi controllare questa condizione per HttpException: httpException.WebEventCode == WebEventCodes.RuntimeErrorPostTooLarge- utilizzando System.Web.Management.WebEventCodes
mco

58

Come ha detto GateKiller, è necessario modificare maxRequestLength. Potrebbe anche essere necessario modificare il timeout di esecuzione nel caso in cui la velocità di caricamento sia troppo lenta. Nota che non vuoi che nessuna di queste impostazioni sia troppo grande altrimenti sarai aperto agli attacchi DOS.

L'impostazione predefinita per il timeout di esecuzione è 360 secondi o 6 minuti.

È possibile modificare maxRequestLength e executionTimeout con l' elemento httpRuntime .

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

MODIFICARE:

Se vuoi gestire l'eccezione a prescindere, come è già stato affermato, dovrai gestirla in Global.asax. Ecco un collegamento a un esempio di codice .


2
Grazie per la tua risposta, ma come ho detto nel mio commento alla risposta di GK questo non risolve davvero il mio problema. Non è nemmeno un problema di timeout, poiché l'eccezione viene generata immediatamente. Modificherò la domanda per renderlo più chiaro.
Marcus L

4
L'URL di esempio di codice punta a una pagina che non è disponibile ... qualcuno può risolvere questo problema?
deostroll

20

Puoi risolvere questo problema aumentando la lunghezza massima della richiesta nel tuo web.config:

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

L'esempio sopra è per un limite di 100 Mb.


18
Sì e no. Spingi oltre il limite, ma in realtà non gestisce l'eccezione. Continuerai a riscontrare lo stesso problema se qualcuno prova a caricare 101+ Mb. Il limite deve essere davvero di 5 Mb.
Marcus L

10

Se si desidera anche una convalida lato client in modo da ottenere meno la necessità di generare eccezioni, è possibile provare a implementare la convalida della dimensione del file lato client.

Nota: funziona solo nei browser che supportano 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

Salve soluzione menzionata da Damien McGivern, funziona solo su IIS6,

Non funziona su IIS7 e ASP.NET Development Server. Ottengo la pagina che mostra "404 - File o directory non trovato".

Qualche idea?

MODIFICARE:

Capito ... Questa soluzione non funziona ancora su ASP.NET Development Server, ma ho capito perché non funzionava su IIS7 nel mio caso.

Il motivo è che IIS7 ha una scansione delle richieste incorporata che impone un limite di file di caricamento che ha un valore predefinito di 30000000 byte (che è leggermente inferiore a 30 MB).

E stavo cercando di caricare file di dimensioni 100 MB per testare la soluzione menzionata da Damien McGivern (con maxRequestLength = "10240" cioè 10 MB in web.config). Ora, se carico il file di dimensioni> 10 MB e <30 MB, la pagina viene reindirizzata alla pagina di errore specificata. Ma se la dimensione del file è> 30 MB, viene visualizzata la brutta pagina di errore incorporata che mostra "404 - File o directory non trovati".

Quindi, per evitare questo, devi aumentare il max. lunghezza del contenuto della richiesta consentita per il tuo sito Web in IIS7. Ciò può essere fatto utilizzando il seguente comando,

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

Ho impostato il max. lunghezza del contenuto fino a 200 MB.

Dopo aver eseguito questa impostazione, la pagina viene reindirizzata con successo alla mia pagina di errore quando provo a caricare un file di 100 MB

Fare riferimento a http://weblogs.asp.net/jgalloway/archive/2008/01/08/large-file-uploads-in-asp-net.aspx per maggiori dettagli.


Scusa! Ho aggiunto la mia query come risposta, non so come aggiungere commenti ai post esistenti.
Vinod T. Patil

1
Hai solo bisogno di più rappresentante. per commentare i post. Vedi le faq per maggiori dettagli su cosa puoi / non puoi fare con il tuo attuale rappresentante.
schifoso

7

Ecco un modo alternativo, che non comporta alcun "hack", ma richiede ASP.NET 4.0 o successivo:

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

4

Un modo per farlo è impostare la dimensione massima in web.config come è già stato detto sopra es

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

quindi quando gestisci l'evento di caricamento, controlla le dimensioni e se è superiore a un importo specifico, puoi intercettarlo ad es

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

1
Questo non funziona. L'evento clic non viene mai attivato. L'eccezione accade prima.
Lombas,


3

In IIS 7 e oltre:

file web.config:

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

Puoi quindi controllare il codice dietro, in questo modo:

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

Assicurati solo che la [Dimensione in byte] nel web.config sia maggiore della dimensione del file che desideri caricare, quindi non otterrai l'errore 404. È quindi possibile controllare la dimensione del file nel codice sottostante utilizzando ContentLength che sarebbe molto meglio


2

Come probabilmente saprai, la lunghezza massima della richiesta è configurata in DUE posti.

  1. maxRequestLength - controllato a livello di app ASP.NET
  2. maxAllowedContentLength- sotto <system.webServer>, controllato a livello IIS

Il primo caso è coperto da altre risposte a questa domanda.

Per catturare IL SECONDO devi farlo in 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();
    }
}

1

Dopo il tag

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

aggiungi il seguente tag

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

puoi aggiungere l'URL alla pagina di errore ...


0

Puoi risolvere questo problema aumentando la lunghezza massima della richiesta e il timeout di esecuzione nel tuo web.config:

-Si prega di chiarire il timeout massimo di esecuzione maggiore di 1200

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

0

Che ne dici di prenderlo all'evento 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

Può essere verificato tramite:

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

                return;

            }
        }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.