1

我花了大部分时间试图弄清楚为什么这不起作用。我有一个将对象流式传输到客户端的 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

4 回答 4

6

我也遇到了这个问题,对我有用的是将流的位置设置为 0,然后再将其发送回客户端。

于 2013-04-12T06:11:02.260 回答
2

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

我也从我的 WCF 服务返回一个流。我也遇到了问题,虽然不是完全相同的问题。希望我找到的解决方案会有所帮助。我在这里找到了解决方案。该解决方案正在处理上传流,但我的下载服务中的实现工作正常。
我的 SO 问题/解决方案在这里(我自己的答案是您可能应该查看的答案,而不是特定于 AJAX 的公认答案)

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

编辑 2:我不会使用服务参考。您可以运行(从 cmd 提示符)“svcutil.exe [mex url]”来获取配置文件和 .cs 文件,这可能比从服务参考中获得的更准确。我的项目中什至没有服务参考,它工作正常。只需将生成的 .cs 文件添加到您的项目中并为此添加“使用”语句。此外,您可以将配置设置添加到客户端上的应用程序或 Web 配置文件中。这 2 个生成的文件是在您运行 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;
}
于 2011-01-05T22:18:30.617 回答
0

他们有什么理由要使用“ BinaryFormatter ”吗?如果不是,您可以像这样从 wcf 返回流

return new FileStream(@"D:\yourFileName.txt", FileMode.Open, FileAccess.Read)

于 2011-01-06T10:53:41.537 回答
0

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

于 2018-11-24T00:27:54.863 回答