Ловля "Перевищена максимальна довжина запиту"


112

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

Проблема полягає в тому, що виняток видається перед натисканням кнопки завантаження, а виняток відбувається перед запуском мого коду. Тож як я можу виловлювати та обробляти виняток?

EDIT: Виняток видається миттєво, тому я майже впевнений, що це не проблема очікування через повільне з'єднання.


5
Хтось пробував це з MVC? Здається, я можу правильно вилучити виняток, але я не можу його зупинити: кожен раз, коли я намагаюся надати сторінку помилок, трапляється той самий виняток.
— Енді,

Це повідомлення про помилку передається IIS, перш ніж потрапити до контролера. Щоб повідомити користувача про те, що файл перевищує максимальний ліміт завантаження (встановлений у веб-налаштуваннях), ви можете безпосередньо перевірити розмір файлу через JS за допомогою події зміни. Наприклад, <input type="file" id="upload" name="upload" onchange="showFileSize();" />всередині showFileSize(), ви можете відобразити повідомлення про помилку на основі розміру вашого файлу через var input = document.getElementById("upload"); var file = input.files[0];та додати тег html.
— Альфред Уоллес

Відповіді:


97

На жаль, не існує простого способу зловити такий виняток. Те, що я роблю, це або перекрити метод 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;
}

2
Дякую. OnError не працював, але Application_Error зробив. Насправді у нас є обробник для цього, але хтось його вимкнув у коді.
— Маркус Л

навіть два роки тому, але я все ж хочу запитати, чи добре це працювало дотепер? чи працює порівняння рядків "GetEntireRawContent" добре? Я не думаю, що це питання очікування. хтось виділяється тим, що вказує на те, щоб я десь розгорнувся щодо цього?
— Елейн

@Elaine Так, ця методика все ще працює з ASP.Net 4.0. Якщо ви намагаєтеся завантажити запит, який перевищує максимальну тривалість запиту ASP.Net видає HttpException з кодом очікування. Погляньте в System.Web.HttpRequest.GetEntireRawContent () за допомогою рефлектора.
— Деміен МакГіверн

12
@ sam-rueby Я не хотів відповідати на рядкове повідомлення про помилку, яке може змінитися через локалізацію.
— Деміен Макгіверн

4
Для .NET 4.0 та новіших версій є кращий спосіб визначити, чи був перевищений максимальний розмір запиту. Ви можете перевірити цю умову на HttpException: httpException.WebEventCode == WebEventCodes.RuntimeErrorPostTooLarge- за допомогою System.Web.Management.WebEventCodes
— mco

58

Як сказав GateKiller, вам потрібно змінити maxRequestLength. Вам також може знадобитися змінити timeTimeout у випадку, якщо швидкість завантаження занадто повільна. Зауважте, що ви не хочете, щоб жоден з цих параметрів був занадто великим, інакше ви будете відкриті для DOS-атак.

За замовчуванням для виконання timeimeout - 360 секунд або 6 хвилин.

Ви можете змінити maxRequestLength та ExecuTimeout за допомогою елемента httpRuntime .

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

Редагувати:

Якщо ви хочете обробляти виняток незалежно від того, як уже було зазначено, вам потрібно буде обробити його в Global.asax. Ось посилання на приклад коду .


2
Дякую за вашу відповідь, але, як я вже говорив у коментарі до відповіді GK, це насправді не вирішує мою проблему. Це також не проблема очікування, оскільки виняток кидається миттєво. Я відредагую це питання, щоб зробити це більш зрозумілим.
— Маркус Л

4
Приклад коду URL-адреси вказує на сторінку, яка недоступна ... може хтось це виправити?
— деостролл

20

Ви можете вирішити це, збільшивши максимальну тривалість запиту у вашій web.config:

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

Наведений вище приклад обмеження 100Mb.


18
Так і ні. Ви просуваєте межу далі, але це не справді справляє виняток. Ви все одно отримаєте ту ж проблему, якщо хтось спробує завантажити 101+ Мб. Обмеження дійсно має бути 5 Мб.
— Маркус Л

10

Якщо ви також бажаєте перевірити клієнтську сторону, тож вам не потрібно скидати винятки, ви можете спробувати здійснити перевірку розміру файлу на стороні клієнта.

Примітка. Це працює лише в браузерах, які підтримують 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

Привіт, рішення, згадане Деміеном Макгіверном, працює лише на IIS6,

Він не працює на IIS7 та сервері розробки ASP.NET. Я отримую сторінку з відображенням "404 - Файл або каталог не знайдено."

Якісь ідеї?

Редагувати:

Зрозумів ... Це рішення все ще не працює на сервері розробки ASP.NET, але я отримав причину, чому він не працював над 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 .


Вибачте! Я додав свій запит як відповідь, я не знаю, як додати коментарі до існуючих публікацій.
— Vinod T. Patil

1
Вам просто потрібно більше представників. коментувати пости. Докладнішу інформацію про те, що ви можете / не можете зробити з вашим поточним представником, див.
— невдалий

7

Ось альтернативний спосіб, який не передбачає жодних "хак", але вимагає 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
    }
}

4

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

1
Це не працює. Подія натискання ніколи не запускається. Виняток відбувається раніше.
— Ломба


3

У 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, що було б набагато краще


2

Як ви, напевно, знаєте, максимальна довжина запиту налаштована у ДВОХ місцях.

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

1

Після тегу

<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 на сторінку помилки ...


0

Ви можете вирішити це, збільшивши максимальну тривалість запиту та час виконання у вашій веб.config:

-Заясніть максимальну тривалість терміну виконання, ніж 1200

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

0

Як щодо ловити це на заході 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

Це можна перевірити за допомогою:

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

                return;

            }
        }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.