Увеличить максимальную длину запроса во время выполнения Http из кода C #

#asp.net

#asp.net

Вопрос:

Как я могу увеличить

из моего кода C #? Я не могу сделать это в Web.config, мое приложение создано для развертывания веб-приложения в IIS.

Комментарии:

1. У вас есть доступ к machine.config файлу?

Ответ №1:

Взгляните на http://bytes.com/topic/asp-net/answers/346534-how-i-can-get-httpruntime-section-page

Вот как вы получаете доступ к экземпляру HttpRuntimeSection. Затем измените свойство maxRequestLength.

Комментарии:

1. 1. Кстати, ПОДСКАЗКА: не отправляйте null в WebConfigurationManager.OpenWebConfiguration(path) . Предложение If null, the root Web.config is opened , похоже, означает не то, что я ожидал, и мне пришлось отправить «~», чтобы получить значение из web.config в корневом каталоге.

Ответ №2:

Альтернативой увеличению максимальной длины запроса является создание реализации IHttpModule. В обработчике BeginRequest возьмите HttpWorkerRequest, чтобы обработать его полностью в вашем собственном коде, вместо того, чтобы позволять реализации по умолчанию обрабатывать его.

Вот базовая реализация, которая будет обрабатывать любой запрос, отправленный в любой файл с именем «dropbox.aspx» (в любом каталоге, независимо от того, существует он или нет):

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace Example
{
    public class FileUploadModule: IHttpModule
    {
        #region IHttpModule Members

        public void Dispose() {}

        public void Init(HttpApplication context)
        {
            context.BeginRequest  = new EventHandler(context_BeginRequest);
        }

        #endregion

        void context_BeginRequest(object sender, EventArgs e)
        {
            HttpApplication application = (HttpApplication)sender;
            HttpContext context = application.Context;
            string filePath = context.Request.FilePath;
            string fileName = VirtualPathUtility.GetFileName( filePath );
            string fileExtension = VirtualPathUtility.GetExtension(filePath);

            if (fileName == "dropbox.aspx")
            {
                IServiceProvider provider = (IServiceProvider)context;
                HttpWorkerRequest wr = (HttpWorkerRequest)provider.GetService(typeof(HttpWorkerRequest));

                //HANDLE REQUEST HERE
                //Grab data from HttpWorkerRequest instance, as reflected in HttpRequest.GetEntireRawContent method.

                application.CompleteRequest(); //bypasses all other modules and ends request immediately
            }
        }
    }
}
  

Вы могли бы использовать что-то подобное, например, если вы внедряете средство загрузки файлов и хотите обрабатывать поток содержимого из нескольких частей по мере его получения, чтобы вы могли выполнить аутентификацию на основе опубликованных полей формы и, что более важно, отменить запрос на стороне сервера еще до получения каких-либо данных файла. Это может сэкономить много времени, если на ранней стадии потока вы сможете определить, что загрузка не авторизована или файл будет слишком большим или превысит дисковую квоту пользователя для dropbox.

Это невозможно сделать с реализацией по умолчанию, потому что попытка получить доступ к свойству формы HttpRequest приведет к тому, что он попытается получить весь поток запросов вместе с проверками максимальной длины запроса. Объект HttpRequest имеет метод под названием «GetEntireRawContent», который вызывается, как только требуется доступ к содержимому. Этот метод начинается со следующего кода:

 HttpRuntimeSection httpRuntime = RuntimeConfig.GetConfig(this._context).HttpRuntime;
int maxRequestLengthBytes = httpRuntime.MaxRequestLengthBytes;
if (this.ContentLength > maxRequestLengthBytes)
{
    if (!(this._wr is IIS7WorkerRequest))
    {
        this.Response.CloseConnectionAfterError();
    }
    throw new HttpException(SR.GetString("Max_request_length_exceeded"), null, 0xbbc);
}
  

Суть в том, что вы будете пропускать этот код и вместо этого внедрять собственную проверку длины содержимого. Если вы используете Reflector для просмотра остальной части «GetEntireRawContent», чтобы использовать его в качестве реализации модели, вы увидите, что он в основном выполняет следующее: вызывает GetPreloadedEntityBody, проверяет, есть ли что-то еще для загрузки, вызывая IsEntireEntityBodyIsPreloaded, и, наконец, выполняет цикл вызовов ReadEntityBody для получения остальных данных. Данные, считываемые GetPreloadedEntityBody и ReadEntityBody, сбрасываются в специализированный поток, который автоматически использует временный файл в качестве резервного хранилища, как только он превышает пороговое значение размера.

Базовая реализация будет выглядеть следующим образом:

 MemoryStream request_content = new MemoryStream();
int bytesRemaining = wr.GetTotalEntityBodyLength() - wr.GetPreloadedEntityBodyLength();
byte[] preloaded_data = wr.GetPreloadedEntityBody();
if (preloaded_data != null)
    request_content.Write( preloaded_data, 0, preloaded_data.Length );
if (!wr.IsEntireEntityBodyIsPreloaded()) //not a type-o, they use "Is" redundantly in the 
{
    int BUFFER_SIZE = 0x2000; //8K buffer or whatever
    byte[] buffer = new byte[BUFFER_SIZE];
    while (bytesRemaining > 0)
    {
        bytesRead = wr.ReadEntityBody(buffer, Math.Min( bytesRemaining, BUFFER_SIZE )); //Read another set of bytes
        bytesRemaining -= bytesRead; // Update the bytes remaining
        request_content.Write( buffer, 0, bytesRead ); // Write the chunks to the backing store (memory stream or whatever you want)
    }
    if (bytesRead == 0) //failure to read or nothing left to read
        break;
}
  

На этом этапе весь ваш запрос будет сохранен в MemoryStream. Однако, вместо того, чтобы загружать весь запрос подобным образом, то, что я сделал, это выгрузил цикл «bytesRemaining» в класс с методом «ReadEnough( int max_index )», который вызывается по запросу из специализированного MemoryStream, который «загружает достаточно» в поток для доступа к запрашиваемому байту.

В конечном счете, эта архитектура позволяет мне отправлять запрос непосредственно анализатору, который считывает данные из потока памяти, и поток памяти автоматически загружает дополнительные данные из рабочего запроса по мере необходимости. Я также реализовал события таким образом, что при анализе каждого элемента потока содержимого, состоящего из нескольких частей, он запускает события, когда идентифицируется каждая новая часть и когда каждая часть полностью получена.

Ответ №3:

Вы можете сделать это в web.config

 <httpRuntime maxRequestLength="11000" />
  

11000 == 11 мб

Комментарии:

1. Не удается выполнить в web.config в соответствии с вопросом