WCF Stream.Read始终在客户端返回0

时间:2011-01-05 21:48:35

标签: c# wcf streaming wcf-streaming

我大部分时间都在努力弄清楚为什么这不起作用。我有一个WCF服务,将对象流式传输到客户端。然后,客户端应该将文件写入其磁盘。但是当我调用stream.Read(buffer, 0, bufferLength)时,它总是返回0.这是我的代码:

namespace StreamServiceNS
{
    [ServiceContract]
    public interface IStreamService
    {
        [OperationContract]
        Stream downloadStreamFile();
    }
}
class StreamService : IStreamService
{
    public Stream downloadStreamFile()
    {
        ISSSteamFile sFile = getStreamFile();
        BinaryFormatter bf = new BinaryFormatter();
        MemoryStream stream = new MemoryStream();
        bf.Serialize(stream, sFile);
        return stream;
    }
}

服务配置文件:

<system.serviceModel>
<services>
  <service name="StreamServiceNS.StreamService">
    <endpoint address="stream" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IStreamService"
              name="BasicHttpEndpoint_IStreamService" contract="SWUpdaterService.ISWUService" />
  </service>
</services>
<bindings>
  <basicHttpBinding>
    <binding name="BasicHttpBinding_IStreamService" transferMode="StreamedResponse" 
             maxReceivedMessageSize="209715200"></binding>
  </basicHttpBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior>
      <serviceThrottling maxConcurrentCalls ="100" maxConcurrentSessions="400"/>
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
  </serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

客户端:

TestApp.StreamServiceRef.StreamServiceClient client = new StreamServiceRef.StreamServiceClient();
        try
        {
            Stream stream = client.downloadStreamFile();
            int bufferLength = 8 * 1024;
            byte[] buffer = new byte[bufferLength];

            FileStream fs = new FileStream(@"C:\test\testFile.exe", FileMode.Create, FileAccess.Write);
            int bytesRead;
            while ((bytesRead = stream.Read(buffer, 0, bufferLength)) > 0)
            {
                fs.Write(buffer, 0, bytesRead);
            }
            stream.Close();
            fs.Close();
        }
        catch (Exception e) { Console.WriteLine("Error: " + e.Message); }

客户端app.config:

    <system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpEndpoint_IStreamService" maxReceivedMessageSize="209715200" transferMode="StreamedResponse">
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://[server]/StreamServices/streamservice.svc/stream"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpEndpoint_IStreamService"
            contract="StreamServiceRef.IStreamService" name="BasicHttpEndpoint_IStreamService" />
    </client>
    </system.serviceModel>

(为简洁而修剪了一些代码)

我已经阅读了有关制作WCF流媒体服务的所有内容,而我的代码与他们的代码没有什么不同。我可以用缓冲替换流,并发送一个很好的对象,但是当我尝试流时,客户端总是将流视为“空”。 testFile.exe已创建,但其大小为0KB。

我错过了什么?


更新
人力资源管理。好吧,我无法调试它,因为当我尝试它时告诉我WCF测试客户端不支持Streams。但是,我知道有什么东西在流中进行,因为如果我没有放入while循环,只有一个fs.Write(...),它会在流关闭后写入8KB。所以有些事情正在发生。

我看了你的帖子并补充道:

[MessageContract]
public class FileDownloadMessage
{
    [MessageBodyMember(Order = 1)]
    public MemoryStream FileByteStream;
}

到我的IStreamService。 downloadStreamFile()现在返回FileDownloadMessage个对象。

但在我的客户端更新服务引用后,它认为downloadStreamFile()会返回TestApp.StreamServiceRef.MemoryStream个对象。
它还创建了一个downloadStreamFileRequest()类,我没有制作它,也不知道它来自哪里。

4 个答案:

答案 0 :(得分:4)

我也有这个问题,对我有用的是在将流发送回客户端之前将流的位置设置为0.

答案 1 :(得分:2)

首先,您是否能够调试服务并查看流在发送到客户端之前是否包含该方面的任何数据?

我也从我的WCF服务返回一个流。我也遇到了问题,但问题并不完全相同。希望我找到的解决方案会有所帮助。我找到了解决方案here。此解决方案正在处理上传流,但我的下载服务中的实现工作正常 我的问题/解决方案是here(我自己的答案是你应该看的那个,而不是接受的答案,因为这是特定于AJAX的)

编辑:基本的不同之处在于我将Stream包装在MessageContract中,我将Stream指定为消息的唯一成员,而basicHttp绑定的“transferMode”属性为“Streamed”。我是WCF的新手,所以我不能确定这会有所帮助,但我希望它能做到!

编辑2 : 我不会使用服务参考。您可以运行(从cmd提示符)'svcutil.exe [mex url]'来获取配置文件和.cs文件,该文件可能比您从服务引用获得的更准确。我的项目中甚至没有服务参考,它工作正常。只需将生成的.cs文件添加到项目中,然后为其添加“using”语句即可。此外,您可以将配置设置添加到客户端上的应用程序或Web配置文件中。这两个生成的文件将在您运行svcutil命令的目录中创建。

DownloadStreamFileRequest类只是客户端在调用服务时传递给base.Channel的请求对象。在我的下面的代码中,它被称为GetExportedFileRequest

在我生成的.cs文件中,我有以下方法返回System.IO.MemoryStream并从FileDownloadMessage对象获取此流:

public System.IO.MemoryStream GetExportedFile()
{
    GetExportedFileRequest inValue = new GetExportedFileRequest();
    FileDownloadMessage retVal = ((IDailyBillingParser)(this)).GetExportedFile( inValue );
    return retVal.FileByteStream;
}

答案 2 :(得分:0)

他们有什么理由要使用“ BinaryFormatter ”吗?如果不是,你可以像wcf那样从

返回流

返回新的FileStream(@“D:\ yourFileName.txt”,FileMode.Open,FileAccess.Read)

答案 3 :(得分:0)

万一有人在这里搜索,我的错误是我的WCF服务返回了FileStream而不是Stream-这总是返回空流。将返回类型更改为Stream可以解决我的问题。