Я нашел решение здесь . Вот мой длинный ответ на случай, если это поможет кому-то в будущем. Во-первых, netTcp не поддерживает потоковую передачу, только буферизацию. В статье говорится, что только basicHttp поддерживает потоковую передачу, но это не так, поскольку я успешно проверил это с помощью wsHttp. В моем файле конфигурации на стороне клиента у меня теперь есть 2 определения привязки; 1 для netTcp, а другой для wsHttp (для всей моей не потоковой связи я все еще хочу использовать netTcp). Если вы используете basicHttp, то вам нужно установить для атрибута 'TransferMode' значение 'Потоковый' - wsHttp не разрешает этот атрибут.
Затем мне пришлось определить новый DataContract в моем сервисе, который определил элемент, который я определил как MessageBodyMember. Этот член имеет тип MemoryStream:
[MessageContract]
public class FileDownloadMessage
{
[MessageBodyMember( Order = 1 )]
public System.IO.MemoryStream FileByteStream;
}
Затем для OperationContract, который первоначально возвращал MemoryStream, я изменил так, чтобы он возвращал новый контракт данных 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 возвращает поток без каких-либо сопутствующих метаданных, поэтому объект 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>