我在这里找到了解决方案。这是我的冗长答案,以防将来对某人有所帮助。首先,netTcp 不支持真正的流式传输,只支持缓冲。文章指出只有 basicHttp 支持流式传输,但事实并非如此,因为我已经使用 wsHttp 成功测试了这一点。在我的客户端配置文件中,我现在有 2 个绑定定义;1 用于 netTcp,另一个用于 wsHttp(对于我所有的非流式通信,我仍然想使用 netTcp)。如果使用 basicHttp,则需要将 'transferMode' 属性设置为 'Streamed' - wsHttp 不允许该属性。
然后我必须在我的服务中定义一个新的 DataContract,它定义了一个我定义为 MessageBodyMember 的成员。该成员属于 MemoryStream 类型:
[MessageContract]
public class FileDownloadMessage
{
[MessageBodyMember( Order = 1 )]
public System.IO.MemoryStream FileByteStream;
}
然后对于最初返回 MemoryStream 的 OperationContract,我修改为返回新的 FileDownloadMessage 数据合约:
[OperationContract]
FileDownloadMessage GetExportedFile();
该合同的实施是:
public FileDownloadMessage GetExportedFile()
{
FileDownloadMessage f = new FileDownloadMessage();
f.FileByteStream = new MemoryStream();
if ( ProgressMonitor.Status == ProcessStatus.CompletedReadyForExport )
{
f.FileByteStream = ProgressMonitor.ExportedFileData;
ProgressMonitor.Status = ProcessStatus.Ready;
}
else
{
f.FileByteStream = null;
}
return f;
}
现在 WCF 服务正在返回没有任何其他随附元数据的 Stream,因此我的网页的 Response 对象可以正确解析流:
MemoryStream ms = new MemoryStream();
string filename = "test.xls";
// the code file from the wcf service includes a get method to get the
// MessageBodyMember directly
ms = streamingClient.GetExportedFile();
byte[] b = ms.ToArray();
ms.Flush();
ms.Close();
Response.Clear();
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader( "Content-Disposition", string.Format( "attachment;filename={0}", filename ) );
Response.AddHeader( "Content-Length", b.Length.ToString() );
Response.BinaryWrite( b );
Response.End();
我的配置看起来像:
<wsHttpBinding>
<binding name="WSHttpBindingEndPoint" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="655360"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
allowCookies="false">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="1638400"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Message">
<transport clientCredentialType="Windows" proxyCredentialType="None"
realm="" />
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
</wsHttpBinding>
<netTcpBinding>
<binding name="NetTcpBindingEndPoint" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
transactionFlow="false" transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10" maxBufferPoolSize="524288"
maxBufferSize="655360" maxConnections="10" maxReceivedMessageSize="655360">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="1638400"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>