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

本文关键字:客户端 不能 一个 | 更新日期: 2023-09-27 18:16:15

在WCF服务中,我根据这个问题填充流,如:

   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; 

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

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

流为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>

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

这真是把我逼疯了!

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

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

哇,我终于成功地实现了我们的场景,要把答案放在这里,也许有人想使用解决方案在一个流中返回多个文件。

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

所以在第一步我已经创建了一个可序列化的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);

一切都很顺利。