一个流中的多个流不会正确传递给客户端

时间:2016-11-04 13:24:43

标签: c# .net wcf stream wcf-binding

在WCF服务中,我根据this question填写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; 

在此之前我通过此返回流,一切都在服务和客户端工作:

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

Stream be MessageBodyMember 但现在坚果改变它以保存一个流中的所有文件。

客户端的

和测试方法:

 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>

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

这真的让我感到震惊!

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

1 个答案:

答案 0 :(得分:1)

哇,最后我成功地正确实现了我们的场景,在这里提出答案可能有人想使用该解决方案在一个流中返回多个文件。

有几个样本要返回多个文件,但是所有这些文件都返回字节数组,我更喜欢返回流因为很多原因,重要的是流对大文件的性能会更好,因为不是所有文件都需要读取一次进入内存并向后兼容我的情况。

因此,在第一步,我创建了一个可序列化的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);

一切都像魅力一样没有任何问题。

享受。