Catching " превышена максимальная длина запроса"

Я пишу функцию загрузки, и у меня проблемы с ловлей "системы.Сеть.HttpException: максимальная длина запроса превышена " с файлами больше указанного максимального размера в httpRuntimeв интернете.config (максимальный размер установлен в 5120). Я использую простой <input> для файла.

проблема в том, что исключение возникает до события click-event кнопки загрузки, и исключение происходит до запуска моего кода. Так как же мне поймать и справиться с исключение?

EDIT: исключение выбрасывается мгновенно, поэтому я уверен, что это не проблема тайм-аута из-за медленных соединений.

13 ответов


к сожалению, нет простого способа поймать такое исключение. Я либо переопределяю метод OnError на уровне страницы, либо Application_Error в global.asax, затем проверьте, был ли это сбой запроса Max и, если да, перейдите на страницу ошибок.

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 минут.

вы можете изменить maxRequestLength и executionTimeout с помощью строки httpruntime Элемент.

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

изменить:

Если вы хотите обработать исключение независимо от того, как уже было указано, вам нужно будет обработать его в Global.асакс. Вот ссылка на пример кода.


вы можете решить эту проблему, увеличив максимальную длину запроса в интернете.config:

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

приведенный выше пример для ограничения 100 МБ.


Привет решение, упомянутое Дэмиеном Макгиверном, Работает только на IIS6,

Он не работает на IIS7 и ASP.NET сервер разработки. Я получаю страницу с надписью "404 - файл или каталог не найден."

какие идеи?

EDIT:

получил его... Это решение все еще не работает ASP.NET сервер разработки, но я получил причину, по которой он не работал на IIS7 в моем случае.

причина в том, что IIS7 имеет встроенное сканирование запросов который накладывает крышку файла загрузки, которая по умолчанию составляет 30000000 байт (что немного меньше 30 МБ).

и я пытался загрузить файл размером 100 МБ, чтобы проверить решение, упомянутое Дэмиеном Макгиверном (с maxRequestLength="10240", т. е. 10 МБ в интернете.конфигурация.) Теперь, если я загружаю файл размером > 10MB и 30MB, то он показывает уродливую встроенную страницу ошибок, отображающую " 404-файл или каталог не найдено."

Итак, чтобы избежать этого, вы должны увеличить max. разрешенная длина содержимого запроса для вашего сайта в IIS7. Это можно сделать, используя следующую команду,

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

Я установил max. длина содержимого до 200 МБ.

после выполнения этой настройки страница успешно перенаправляется на мою страницу ошибок при попытке загрузить файл 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>


один из способов сделать это-установить максимальный размер в интернете.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";
    }
}

вот альтернативный способ, который не включает никаких "хаков", но требует 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
    }
}


в IIS 7 и за его пределами:

web.конфигурационный файл:

<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

просто убедитесь, что [размер в байтах] в интернете.config больше размера файла, который вы хотите загрузить, тогда вы не получите ошибку 404. Затем вы можете проверить размер файла в коде, используя ContentLength, который был бы намного лучше


как вы, вероятно, знаете, максимальная длина запроса настроена в два места.

  1. maxRequestLength - контролируется на ASP.NET уровень приложения
  2. maxAllowedContentLength - под <system.webServer>, управляется на уровне IIS

первый случай охвачен другими ответами на этот вопрос.

поймать ВТОРОЙ вам нужно сделать это в глобальном масштабе.асакс:

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-адрес на страницу ошибки...


вы можете решить эту проблему, увеличив максимальную длину запроса и время выполнения в интернете.config:

- пожалуйста, уточните максимальное время выполнения терки, то 1200

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

Как насчет поймать его на мероприятии 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);
        }
    }