一个流中的多个流将无法正确传递给客户端

Multiple stream in one stream will not passed to client properly

在 WCF 服务中,我根据 填充 Stream,例如:

   result.Stream = new MemoryStream();
            BinaryWriter writer = new BinaryWriter(result.Stream);
            foreach (string fileN in zipFiles)
            {
                byte[] fileBytes = File.ReadAllBytes(fileN);
                writer.Write(BitConverter.GetBytes(fileBytes.Length), 0, 4);
                writer.Write(fileBytes, 0, fileBytes.Length);
            }
            writer.Flush();
            return result; 

在此之前,我return通过这个流式传输并且一切都在服务端和客户端工作:

 result.Stream = new MemoryStream(File.ReadAllBytes(fileN));

流成为 MessageBodyMember 但 nut 现在将其更改为将所有文件保存在一个流中。

客户端测试方法:

 ExportClient export = new ExportClient("exportEndPoint");
        ExportResult_C result = export.Export(source);
        result.Stream.Position = 0;
        //result.Stream.SaveToFile("d:\kkk.log");
        BinaryReader reader = new BinaryReader(result.Stream, System.Text.Encoding.UTF8);
        string pathToSave = string.Empty;
        while (result.Stream.Position < result.Stream.Length)
        {
            int size = reader.ReadInt32();
            byte[] data = reader.ReadBytes(size);
            pathToSave = "D:\test\" + new Random().Next(0, 2564586).ToString() + ".zip";
            File.WriteAllBytes(pathToSave, data);
        }

端点地址:

 <endpoint address="net.tcp://localhost:2082/Exchange/Export.svc" binding="netTcpBinding" bindingConfiguration="largeSizeStreamTcp"
    contract="xxx" name="exportEndPoint"/>

和绑定配置:

 <netTcpBinding>
    <binding openTimeout="00:00:03" maxReceivedMessageSize="2000000000" transferMode="Streamed" maxBufferSize="2000000000" >
      <readerQuotas maxDepth="32" maxArrayLength="2000000000" maxStringContentLength="2000000000" />
      <security mode="None" />
    </binding>
    <binding name="largeSizeStreamTcp"  transferMode="Streamed" receiveTimeout="00:30:00" sendTimeout="00:30:00" openTimeout="00:00:01" maxReceivedMessageSize="2000000000" maxBufferSize="2000000000" >
      <readerQuotas maxDepth="32" maxArrayLength="2000000000" maxStringContentLength="2000000000" />
      <security mode="None" />
    </binding>
  </netTcpBinding>
  <netNamedPipeBinding>

我相信端点和绑定是正确的,因为我能够 return 一个文件流并将其保存回来,但现在服务端没有问题,但是当它从客户端获取时,Stream 丢失了它的内容、长度、位置。

这真的让我很生气!!!

有谁知道为什么会发生这种情况(在客户端)?

Wooow,我终于成功地正确实施了我们的方案,将答案放在这里也许有人想使用该解决方案在一个流中处理 returns 多个文件。

有几个示例到 return 多个文件,但它们都是 returning 字节数组,我更喜欢 return 流,因为很多原因,重要的是流对于大文件会表现得更好,因为不是所有的文件都需要一次读入内存并且向后兼容我的情况。

所以在第一步我创建了一个可序列化的DataContract来保存文件名及其内容字节。

[DataContract]
[Serializable]
public class ExportSourceFiles_C
{
    [DataMember]
    public string Name;
    [DataMember]
    public byte[] Content;
}

第二步 将创建 ExportSourceFile_C 的列表,如下所示:

List<ExportSourceFiles_C> sourceFiles = new List<ExportSourceFiles_C>();
string[] zipFiles = Directory.GetFiles(zipRoot);
foreach (string path in zipFiles)
  {
     byte[] fileBytes = File.ReadAllBytes(path);
     sourceFiles.Add(new ExportSourceFiles_C()
     {
         Name = Path.GetFileName(path),
         Content = fileBytes
     });
  }

第三步,提到的列表应该序列化为result.Stream,如:

  result.Stream = new MemoryStream();
  BinaryFormatter formatter = new BinaryFormatter();
  formatter.Serialize(result.Stream, sourceFiles);
  result.Stream.Position = 0;
  return result;

在客户端,这足以将流反序列化为 ExportSourceFiles_C 的列表,因此客户端的最后一步应该是这样的:

 ExportClient export = new ExportClient("exportEndPoint");
 ExportResult_C result = export.Export(source);
 BinaryFormatter formatter = new BinaryFormatter();
 List<ExportSourceFiles_C> deserialisedFiles = (List<ExportSourceFiles_C>)formatter.Deserialize(result.Stream);
 foreach (ExportSourceFiles_C file in deserialisedFiles)
      File.WriteAllBytes("d:\" + file.Name, file.Content);

一切正常,没有任何问题。

尽情享受吧。