繁体   English   中英

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

[英]How can I stream a response from WCF without buffering?

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

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

我尝试过AnonymousPipeServerStreamWCF和流请求和响应

以及第一个设置:

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)。

<services>
  <service name="CustomersService">
    <endpoint address="FilesService.svc" binding="basicHttpBinding" bindingConfiguration="StreamedBinding" contract="Soap.Interfaces.IFilesService" />
  </service>
</services>

并定义绑定配置:

<bindings>
    <basicHttpBinding>
        <binding name="IntersolveWebServicesStreamedBinding" allowCookies="true" transferMode="Streamed" maxReceivedMessageSize="67108864" />
    </basicHttpBinding>
</bindings>

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM