Подтвердить что ты не робот

Поддержка потокового запроса WebAPI

Я пишу приложение ASP.NET Web API, которое требует, чтобы я принимал загрузку файла и пересылал его на другую конечную точку HTTP.

Я обеспокоен тем, что если многие пользователи пытаются загрузить файл по 100 Мбайт каждый (что является допустимым вариантом использования), то мое приложение будет иметь большой объем памяти и в зависимости от объема больших запросов этот размер может увеличиться до большого, а мой приложение будет зависеть и умереть.

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

Я уверен, что этот процесс имеет имя, но я этого не знаю, что делает поиск его довольно жестким.

Я провел довольно много работы с потоком ответов в веб-API, но мне никогда не приходилось рассматривать потоки запросов раньше.

Лучше всего я могу сказать, что мне нужно разобраться, как:

  • Начните обработку потока до его завершения.
  • Используйте HttpClient для потока одного и того же запроса для передачи тех же данных в другую конечную точку HTTP.

Может кто-нибудь предложить мне некоторые указатели?

4b9b3361

Ответ 1

Это интересный вопрос. Я постараюсь сделать все возможное, чтобы дать некоторые общие указатели.

Немного о чем подумать:

1) Web API по умолчанию буферизует запросы, поэтому ваш страх, что объем памяти может быть значительным, определенно оправдан. Вы можете заставить Web API работать с запросами в потоковом режиме:

    public class NoBufferPolicySelector : WebHostBufferPolicySelector
    {
       public override bool UseBufferedInputStream(object hostContext)
       {
          var context = hostContext as HttpContextBase;

          if (context != null)
          {
             if (string.Equals(context.Request.RequestContext.RouteData.Values["controller"].ToString(), "uploading", StringComparison.InvariantCultureIgnoreCase))
                return false;
          }

          return true;
       }

       public override bool UseBufferedOutputStream(HttpResponseMessage response)
       {
          return base.UseBufferedOutputStream(response);
       }
    }

И затем замените службу:

GlobalConfiguration.Configuration.Services.Replace(typeof(IHostBufferPolicySelector), new NoBufferPolicySelector());

Обратите внимание, что из-за различий между WebHost и SelfHost в данный момент такое изменение возможно только в WebHost. Если ваша конечная точка selfHosted, вам необходимо установить режим потоковой передачи на уровне GlobalConfig:

//requests only
selfHostConf.TransferMode = TransferMode.StreamedRequest;
//responses only
selfHostConf.TransferMode = TransferMode.StreamedResponse;
//both
selfHostConf.TransferMode = TransferMode.Streamed;

Я уже подробно рассказывал о работе с большими файлами в Web API более подробно - http://www.strathweb.com/2012/09/dealing-with-large-files-in-asp-net-web-api/, так что, надеюсь, вы найдете это полезным.

2). Во-вторых, если вы используете HttpClient, в .NET 4 он по умолчанию загружает тело запросов, поэтому вы действительно должны использовать .NEt 4.5.

Если вам нужно использовать .NET 4, вам нужно напрямую работать с HttWebRequest:  - http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.allowreadstreambuffering.aspx  - http://msdn.microsoft.com/en-us/library/system.net.httpwebrequest.allowwritestreambuffering.aspx

3) Что касается нажатия на данные клиенту, что определенно возможно, если вы хотите сделать это, PushStreamContent. Здесь у Хенрика есть короткий вводный пост - http://blogs.msdn.com/b/henrikn/archive/2012/04/23/using-cookies-with-asp-net-web-api.aspx (он основан на битах веб-API RC, поэтому вам может понадобиться настроить некоторые подписи и т.д.) Я также писал о том, что здесь выжимают куски данных потока - http://www.strathweb.com/2013/01/asynchronously-streaming-video-with-asp-net-web-api/

EDIT: Чтобы увидеть пример, если PushStreamContent в запросе, вы можете посмотреть это примерное решение - < а5 >