一个流中的多个流不能正确传递给客户端
本文关键字:客户端 不能 一个 | 更新日期: 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);
一切都很顺利。
。