Перехват "Превышена максимальная длина запроса" - PullRequest
107 голосов
/ 20 марта 2009

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

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

РЕДАКТИРОВАТЬ: Исключение выдается мгновенно, поэтому я уверен, что это не проблема тайм-аута из-за медленных соединений.

Ответы [ 14 ]

95 голосов
/ 20 марта 2009

К сожалению, не существует простого способа отловить такое исключение. Я перезаписываю метод OnError на уровне страницы или Application_Error в global.asax, затем проверяю, не произошел ли сбой 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;
}
58 голосов
/ 20 марта 2009

Как сказал GateKiller, вам нужно изменить maxRequestLength. Вам также может понадобиться изменить executeTimeout, если скорость загрузки слишком низкая. Обратите внимание, что вы не хотите, чтобы какой-либо из этих параметров был слишком большим, иначе вы будете открыты для атак DOS.

Значение по умолчанию для executeTimeout составляет 360 секунд или 6 минут.

Вы можете изменить maxRequestLength и executeTimeout с помощью элемента httpRuntime .

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

EDIT:

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

20 голосов
/ 20 марта 2009

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

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

В приведенном выше примере указан предел в 100 МБ.

9 голосов
/ 05 июля 2011

Если вам нужна проверка на стороне клиента, и вам не нужно создавать исключения, вы можете попытаться реализовать проверку размера файла на стороне клиента.

Примечание: это работает только в браузерах, которые поддерживают 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 голосов
/ 07 июля 2010

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

Не работает на IIS7 и ASP.NET Development Server. Я получаю страницу с сообщением «404 - Файл или каталог не найден».

Есть идеи?

EDIT:

Понятно ... Это решение до сих пор не работает на ASP.NET Development Server, но у меня есть причина, почему оно не работает на IIS7 в моем случае.

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

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

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

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

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

После выполнения этой настройки страница успешно перенаправляется на страницу ошибок при попытке загрузить файл размером 100 МБ

Подробнее см. http://weblogs.asp.net/jgalloway/archive/2008/01/08/large-file-uploads-in-asp-net.aspx.

5 голосов
/ 23 мая 2015

Вот альтернативный способ, который не включает никаких «хаков», но требует 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
    }
}
5 голосов
/ 15 сентября 2012

Один из способов сделать это - установить максимальный размер в файле 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";
    }
}
3 голосов
/ 23 июня 2014

В 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 больше, чем размер файла, который вы хотите загрузить, тогда вы не получите ошибку 404. Затем вы можете проверить размер файла в коде, используя ContentLength, который был бы намного лучше

3 голосов
/ 24 сентября 2010
2 голосов
/ 22 декабря 2016

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

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

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

Чтобы поймать ВТОРОЙ ОДИН , вам нужно сделать это в 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();
    }
}
...