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


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.