2013-01-22 12 views
25

Piszę aplikację ASP.NET Web API, która wymaga ode mnie zaakceptowania przesłania pliku i przekazania tego pliku do innego punktu końcowego HTTP.WebAPI Wniosek Obsługa przesyłania strumieniowego

Obawiam się, że jeśli wielu użytkowników spróbuje załadować każdy plik o wielkości 100 MB (co jest ważnym przypadkiem użycia), wówczas moja aplikacja będzie miała duży rozmiar pamięci i w zależności od wielkości dużych żądań, ten ślad może wzrosnąć do dużego i moja aplikacja zgnije i umrze.

Idealnie chciałbym rozpocząć przesyłanie strumieniowe pliku do drugiego punktu końcowego HTTP, gdy tylko serwer WWW zacznie otrzymywać plik, aby znacząco zmniejszyć obciążenie serwera.

Jestem pewien, że proces ten ma nazwę, ale nie wiem, co powoduje, że wyszukiwanie jest dość trudne.

Zrobiłem sporo pracy ze Streamingiem Odpowiedzi w Web API, ale nigdy wcześniej nie musiałem rozważać przesyłania żądania.

najlepsze, co mogę powiedzieć muszę wypracować jak:

  • rozpoczęciem przetwarzania strumienia zanim zakończy ładowanie.
  • Użyj HttpClient, aby przesłać strumieniowo to samo żądanie, aby przesłać te same dane do innego punktu końcowego HTTP.

Czy ktoś może zaoferować mi jakieś wskazówki?

+1

Co MultipartStreamProvider pan skończyć używając aby było to możliwe? Staram się osiągnąć dokładnie to samo ... Czy możesz podzielić się swoim kodem kontrolera? – Bredstik

Odpowiedz

38

To interesujące pytanie. Postaram się zrobić co w mojej mocy, aby podać ogólne wskazówki.

kilka rzeczy do rozważenia:

1) Web API domyślnie bufory żądań więc obawa, że ​​zużycie pamięci może być znaczna jest z pewnością uzasadnione. Można wymusić Web API do pracy z wnioskami w trybie strumieniowej:

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

a następnie zastąpić usługę:

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

Zwróć uwagę, że ze względu na różnice między witryną i SelfHost w tym momencie taka zmiana jest możliwe tylko w WebHost. Jeśli punkt końcowy jest selfHosted, trzeba by ustawić tryb strumieniowania na poziomie GlobalConfig:

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

Mam blogu na temat radzenia sobie z dużymi plikami w sieci Web API dokładniej wcześniej - http://www.strathweb.com/2012/09/dealing-with-large-files-in-asp-net-web-api/ więc miejmy nadzieję, przekonasz się, że przydatny. Po drugie, jeśli używasz HttpClient, w .NET 4 buforuje domyślnie treść żądania, więc powinieneś naprawdę użyć .NEt 4.5.

Jeśli trzeba użyć .NET 4 masz do pracy z HttWebRequest bezpośrednio: - 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) Jeśli chodzi o przesuwanie danych do klienta, który jest na pewno możliwe, jeśli chcesz zrób to z PushStreamContent. Henrik ma krótki słupek wprowadzający tutaj - http://blogs.msdn.com/b/henrikn/archive/2012/04/23/using-cookies-with-asp-net-web-api.aspx (nie jest to oparte na sieci Web API bitów RC więc może trzeba dostosować niektóre podpisy itd) ja też napisał o popychanie ilości danych strumienia tutaj - http://www.strathweb.com/2013/01/asynchronously-streaming-video-with-asp-net-web-api/

EDIT: aby zobaczyć przykład jeśli PushStreamContent we wniosku, można przyjrzeć się tej próbki roztworu - http://aspnet.codeplex.com/SourceControl/changeset/view/bb167f0b0013#Samples/Net45/CS/WebApi/UploadXDocumentSample/ReadMe.txt

+0

Nie zdawałem sobie sprawy, że będę mógł użyć PushStreamContent podczas wysyłania żądania. Używałem ich tylko w odpowiedzi. Na szczęście korzystamy z .NET 4.5 - czy to oznacza, że ​​HttpClient nie buforuje żądań? –

+0

Tak - HttpClient w .NET 4.5 domyślnie nie buforuje żądań. W .NET 4 ma to (oznacza załadowanie całego żądania do pamięci, a następnie wysłanie). –

+0

Dodałem jeszcze jedno odniesienie do próbki w odpowiedzi (PushStreamContent w żądaniu). –

Powiązane problemy