c# - 传输大文件 : combining streamed transfer and content-length

标签 c# wcf http browser http-headers

TL;DR:如何使用 WCF 流式传输已知大小的大文件,并且仍然向最终用户(网络浏览器)显示进度(Content-Length)?

我有一个 WCF REST 服务,可以下载非常大的文件 (1-20Gb),然后将其提供给 Web 浏览器。为简化起见,将我的服务视为代理。这迫使我在绑定(bind)上设置 TransferMode = StreamedTransferMode = StreamedResponse,否则最终客户端将不得不等待源文件在实际下载开始。此外,缓冲传输模式会因大文件(RAM 使用)而终止服务器。中间磁盘存储不是一种选择。来自 TransferMode 手册页:

(...) Buffered transfers hold the entire message in a memory buffer until the transfer is complete.

但是当设置 TransferModeStreamedStreamedResponse 时,WCF 不再返回 header Content-length 到客户端,并添加了一个新的 header Transfer-Encoding: chunked。这与 wikipedias article on chunked transfer 是一致的:

(...) uses the Transfer-Encoding HTTP header in place of the Content-Length header (...)

但我总是事先知道要传输的数据的大小,对于最终用户来说,不知道下载的大小是非常令人沮丧的。所以:

(如何)我可以将 WCF 绑定(bind)配置为使用“流”传输模式(更具体地说,在发送之前缓冲整个消息)并且仍然使用 Content-Length 标题?

一些线索:

  • This q/a 声明 http 标准不允许在同一消息中同时使用 Transfer-EncodingContent-length: 123456,所以我猜这不是一个选项?

  • 我尝试使用 IDispatchMessage.BeforeSendReply 中的检查器修改 header ,但此时 Content-Length header 尚未删除,并且 Transfer-Encoding还没有定下来,所以“太早了”。后来我读到分块传输编码是在 TCP 级别上进行的,因此即使我可以,此时更改 header 也可能不会起作用。

  • 我尝试设置 aspNetCompatibilityEnabled ="true",将 wcf 传输模式设置为缓冲输出(默认),然后设置 System.Web.HttpContext.Current.Response.BufferOutput =假;。虽然 wcf 忽略了这一点,但消息显然已被缓冲。

  • 根据 this link 的说法,这似乎是一项缺失的功能。但是某处可能仍然有一个古怪的解决方法..

最佳答案

这是一个经过测试的解决方法,仅适用于 IIS 下的 WCF - 我还没有找到任何自托管服务的解决方案。

简而言之 - 打开 aspNetCompatibility这使您可以在运行时访问 System.Web.HttpContext.Current .

Web.config :

(...)
    <system.serviceModel>
      <bindings>
          <webHttpBinding>
              <binding transferMode="Streamed">
              </binding>
          </webHttpBinding>
      </bindings>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
(...)
</system.serviceModel>

并在返回流的服务函数中:

HttpContext.Current.Response.Headers.Add("Content-Length", 
contentLength.ToString());

以下任何内容都将被忽略:

<罢工>

<罢工>
WebOperationContext.Current.OutgoingResponse.Headers["Content-Length"] = 
        contentLength.ToString();

<罢工>

就这么简单!积分转到Uffe Lausen's question on Msdn

关于c# - 传输大文件 : combining streamed transfer and content-length,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22220798/

相关文章:

访问 TFS 的 C# 自定义应用程序

c# - WCF Rest WebFaultException 总是返回 202

c# - 回收 Worker 进程对 WCF 服务的影响

http - URL:带@的用户名

ajax - 在同一域中发送不带 cookie 的 ajax 请求?

c# - 带有 Toastr 的 ASP.Net MVC C# 不缩小 javascript

c# - TypeInitializationException C# 使用 mysql 连接

c# - 无法排序,因为 IComparer.Compare() 方法返回不一致的结果。再次

wcf - 可以将 WCF 日志记录配置为使用 shell 文件夹路径吗?

android - 如何在安卓上通过 ssl (https) 下载文件