WebAPI请求流支持

时间:2013-01-22 06:34:46

标签: c# asp.net streaming asp.net-web-api

我正在编写一个ASP.NET Web API应用程序,它要求我接受文件上载并将该文件转发到另一个HTTP端点。

我担心如果许多用户尝试上传每个100MB的文件(这是一个有效的用例),那么我的应用程序将占用大量内存,并且根据大量请求的数量,这个足迹可能会变大,而我的申请会结束并死亡。

理想情况下,只要Web服务器开始接收文件以显着减少服务器上的负载,我就会开始将文件流式传输到其他HTTP端点。

我确信这个过程有一个名字,但我不知道 - 这使得搜索相当艰难。

我在Web API中使用Response Streaming做了很多工作,但我以前从未考虑过请求流。

最好我可以告诉我需要弄清楚如何:

  • 在完成上传之前开始处理流。
  • 使用HttpClient流式传输相同的请求,以将相同的数据流式传输到其他HTTP端点。

有人可以给我一些指示吗?

1 个答案:

答案 0 :(得分:42)

这是一个有趣的问题。我会尽力给出一些一般性的指示。

很少有事情需要考虑:

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将数据推送到客户端,那么这绝对是可能的。 Henrik在这里有一篇简短的介绍性帖子 - 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