如何在不缓冲的情况下从WCF流式传输响应?

我有一个restful(webHttpBinding)自托管WCF服务。 大多数方法都将xml或json版本的对象返回给客户端。

我有几个触发长时间运行方法的GET方法,我想将日志响应流式传输到浏览器(或应用程序),以便用户知道发生了什么。 使用HttpContext.Current.Response.OutputStream.Write可以很容易地实现这一点。 不幸的是, HttpContext.Current在自托管WCF服务中始终为null,即使我包含aspNetCompatibilityEnabled配置(遗憾的是IIS不是一个选项)。

我尝试过AnonymousPipeServerStream : WCF和流请求和响应

以及第一个设置:

 OutgoingWebResponseContext context = WebOperationContext.Current.OutgoingResponse; context.ContentType = "text/plain"; 

这样响应进入浏览器就不会将流下载到文件中进行保存。

在Chrome中它根本不起作用 – 它会缓冲到最后。 在IE或wget中,它似乎一次缓冲大约4k(或其他东西)。 这对于日志记录没有好处,除非我吐出大量不必要的日志消息来强制输出,用户并不真正知道发生了什么。 我只能假设这是因为响应实际上是一个分块响应而且块是4k(而不是只写入输出流)。

将chrome输出到输出的修复显然是在发送分块响应之前给内容写了一些垃圾: Chunked transfer encoding – 浏览器行为 ,但是,我不认为这对于WCF是可能的。

那么,我正在寻找可能的解决方案:

  • 一种在自托管服务(无IIS)中写入WCF中的输出流的方法。 要么
  • 一种控制流响应中的块大小的方法(以及首先编写一些内容以便Chrome将呈现块的方式)。

我认为另一种选择是放弃WCF,转而支持更友好的REST(我开始认为WCF不是正确的选择)。 但是,现在在WCF中写了这么多,这似乎是一项乏味的任务。 除非有一些我可以切换到的东西,这将是一个简单的迁移(例如,如果我可以重用相同的服务类,可能只有不同的属性)。 南希也许?

我做过类似你在这里问的事情 – 自我托管。 我写了一个WCF(BasicHttpBinding)服务,它将数据的流式传输和缓冲都传递给使用我的数据同步服务的客户端设备。 流式传输很难,你可能已经想到了,我认为没有办法“写​​入流”。

从基本的意义上讲,通过WCF服务进行流式传输的方式与File.IO的工作方式相同,如下面的代码所示

  FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read); BinaryReader br = new BinaryReader(fs); 

如果有问题的文件是1 GB,您的文件流将在读取到文件末尾之前开始返回字节。 通过WCF流​​式传输的工作方式相同(事实上,根据我的经验,它实现了FileStream),这就是为什么它对大量数据有利。 它读取……它发送; 它读取……它发送。 所以我不确定你是如何将一些信息注入到该流中以输出到屏幕上的。

话虽如此,我们的Synch UI会显示下降的字节数,加上完成百分比,以防止用户关闭机器或取消。 我们这样做是通过让一个单独的线程每10秒读取下载文件的大小并计算整体的百分比(完整的大小作为响应中的参数发回),然后将结果写入UI结果窗口。 因此,在我们的案例中,解决方案实际上非常简单。

我像这样传输文件:

将返回需要流式传输的数据的方法分组到端点,然后在该端点上添加流式传输模式。

这是我使用的配置(用于basicHttpBinding)。

      

并定义绑定配置:

      

基本上,您必须在绑定配置中设置transferMode。

我没有用webHttpBinding尝试过,所以请告诉我它是否适合你。

只是欺骗浏览器认为有一个带有Multipart Content-Type的HTML响应

http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html

我已经将它用于包括MJPEG在内的很多东西,但你也可以将它用于COMET / WebSocket之类的响应。