2013-01-22 104 views
25

我正在編寫一個ASP.NET Web API應用程序,它要求我接受文件上載並將該文件轉發到另一個HTTP端點。WebAPI請求流支持

我擔心如果許多用戶每次嘗試上傳一個100MB文件(這是一個有效的用例),那麼我的應用程序將具有較大的內存佔用量,並且取決於大量請求的數量,此佔用空間可能會變大並且我的應用程序會崩潰並死亡。

理想情況下,只要Web服務器開始接收文件以顯着減少服務器上的負載,我就想開始將文件流式傳輸到另一個HTTP端點。

我確定這個過程有一個名字,但我不知道它 - 這是在尋找它相當艱難。

我已經在Web API中做了很多與Response Streaming有關的工作,但我從來沒有必須考慮過請求流。

盡我所能告訴我需要找出如何:

  • 開始處理數據流,它已經完成,然後再上傳。
  • 使用HttpClient流式傳輸相同的請求,以將相同的數據流式傳輸到另一個HTTP端點。

任何人都可以給我一些指針嗎?

+1

您最終使用了哪種MultipartStreamProvider來實現此目的?我正在努力實現完全相同的目標......你能分享你的控制器的代碼嗎? – Bredstik

回答

38

這是一個有趣的問題。我會盡我所能給出一些通用的指示。

幾件事情要考慮:

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

請注意,由於在這一點上,這種改變虛擬主機提供商和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/所以希望你會發現,有用。其次,如果你使用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(它是基於Web的API RC位,所以你可能需要調整一些簽名等) 我也博客上講述這裏推流的數據塊 - http://www.strathweb.com/2013/01/asynchronously-streaming-video-with-asp-net-web-api/

編輯:要查看請求中的示例PushStreamContent,您可以查看此示例解決方案 - http://aspnet.codeplex.com/SourceControl/changeset/view/bb167f0b0013#Samples/Net45/CS/WebApi/UploadXDocumentSample/ReadMe.txt

+0

我沒有意識到我可以在發出請求時使用PushStreamContent。我只用過他們的迴應。幸運的是,我們正在使用.NET 4.5 - 那麼這是否意味着HttpClient不會緩衝請求呢? –

+0

是的 - 默認情況下,.NET 4.5中的HttpClient不緩衝請求。在.NET 4中它確實(意味着將整個請求加載到內存中,然後發送)。 –

+0

我在響應中添加了一個更多示例引用(請求中的PushStreamContent) –