Tew*_*ewr 6 c# browser wcf http http-headers
TL; DR:如何使用WCF流式传输已知大小的大文件,并仍Content-Length向最终用户(Web浏览器)显示progress()?
我有一个WCF REST服务,可以下载然后将非常大的文件(1-20Gb)提供给Web浏览器.为简化起见,请将我的服务视为代理.这要求我设置TransferMode = Streamed或TransferMode = StreamedResponse绑定Binding,或者最终客户端必须等待源文件在实际下载开始之前下载到Web服务器.此外,缓冲传输模式会杀死服务器以获取大文件(RAM使用情况).中间磁盘存储不是一种选择.从TransferMode手册页:
(...) 缓冲传输将整个消息保存在内存缓冲区中,直到传输完成.
但是当设置TransferMode为Streamed或时StreamedResponse,WCF不再将标头返回Content-length给客户端,并Transfer-Encoding: chunked添加新标头.这与关于分块传输的wikipedias文章一致:
(...)使用Transfer-Encoding HTTP标头代替 Content-Length标头(...)
但是我总是知道要预先传输的数据的大小,对于最终用户来说,不知道下载的大小是非常令人沮丧的.所以:
(如何)我可以配置WCF绑定以使用"流"传输模式(更具体地说,在发送之前不缓冲整个消息)仍然使用Content-Length标头?
一些线索:
此Q/A状态的HTTP标准不允许两者Transfer-Encoding并Content-length: 123456在同一消息中,所以我想这是不是一种选择?
我已尝试使用IDispatchMessage.BeforeSendReply中的检查器修改标头,但此时Content-Length标头尚未删除,Transfer-Encoding尚未设置,因此它"太早".我后来读到了chunked传输编码是在TCP级别上,所以即使我可以,此时更改标头也许不会工作.
我尝试设置aspNetCompatibilityEnabled="true",将wcf传输模式设置为缓冲输出(默认)然后设置System.Web.HttpContext.Current.Response.BufferOutput = false;.但这被wcf忽略,消息显然是缓冲的.
根据这个链接,它似乎是一个缺失的功能.但某些地方可能还有一个古怪的解决方法..
这是一个经过测试的解决方法,仅适用于 IIS 下的 WCF - 我还没有找到任何自托管服务的解决方案。
简而言之,打开aspNetCompatibility,它可以让您在运行时访问System.Web.HttpContext.Current。
Web.config:
(...)
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding transferMode="Streamed">
</binding>
</webHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
(...)
</system.serviceModel>
Run Code Online (Sandbox Code Playgroud)
并在返回 Stream 的服务函数中:
HttpContext.Current.Response.Headers.Add("Content-Length",
contentLength.ToString());
Run Code Online (Sandbox Code Playgroud)
任何类似以下内容的内容都将被默默忽略:
WebOperationContext.Current.OutgoingResponse.Headers["Content-Length"] =
contentLength.ToString();
Run Code Online (Sandbox Code Playgroud)
就那么简单!Creds 转至Uffe Lausen 在 Msdn 上提出的问题