[英]Best way to return large file as split zip files,Stream or Byte array WCF
我已经将zip文件流作为以下MessageContract
返回给客户端:
[MessageContract]
public class ExportResult_C
{
[MessageHeader]
public PackedStudy_C[] PackedStudy
{
get;
set;
}
[MessageBodyMember]
public Stream Stream
{
get;
set;
}
}
当文件长度超过500 MB时,我决定将其拆分为zip部分。
场景:
1-用户将调用Export方法,该方法返回ExportResult_C
2-如果请求的文件大于500 MB,则将其拆分为较小的部分,即每个部分的大小必须为200MB。
3-如果请求的文件小于500 MB,则返回一个流的MessageContract
。
描述:
为了向后兼容,我决定将ExportResult_C
更改为具有两个属性,一个名为Stream
,该属性已经设计用于文件小于500 MB的情况,另一属性将是流的数组,以容纳200 MB大小的所有拆分zip。
题:
1- MessageContract
可以有另一个流数组支持吗?
2-如果不是,是否可以将Stream
属性更改为Stream类型的数组?
3-或者要实施上述方案,我必须完全更改合同,或者有更好的主意(在吞吐量和向后兼容性方面)?
我想分享我的调查结果和将大文件作为流传递给客户消费者的解决方案:
问题1:
这不可能使MessageBodyMember
具有Stream
或任何其他类型,在运行代码之后,您可能会收到如下异常:
为了将Streams与MessageContract编程模型一起使用,类型yourMessageContract必须具有具有MessageBodyMember属性的单个成员,并且成员类型必须为Stream。
问题2:
我将合同更改为像我想要的那样有一个名为Stream
的支持成员, Streams
是Streams
的数组:
[MessageBodyMember]
public Stream[] Streams
{
get;
set;
}
我的一段代码将大文件拆分为zip部分,并将每个部分的Streams
转换为Streams
例如:
ZipFile zip = new ZipFile();
if (!Directory.Exists(zipRoot))
Directory.CreateDirectory(zipRoot);
zip.AddDirectory(packageSpec.FolderPath, zipRoot);
zip.MaxOutputSegmentSize = 200 * 1024 * 1024; // 200 MB segments
zip.Save(fileName);
ExportResult_C result = null;
if (zip.NumberOfSegmentsForMostRecentSave > 1)
{
result = new ExportResult_C()
{
PackedStudy = packed.ToArray(),
Streams = new Stream[zip.NumberOfSegmentsForMostRecentSave]
};
string[] zipFiles = Directory.GetFiles(zipRoot);
foreach (string fileN in zipFiles)
{
Stream streamToAdd = new MemoryStream(File.ReadAllBytes(fileN));
result.Streams[zipFiles.ToList().IndexOf(fileN)] = streamToAdd;
}
}
else
{
result = new ExportResult_C()
{
PackedStudy = packed.ToArray(),
Streams = new Stream[1] { new MemoryStream(File.ReadAllBytes(fileName)) }
};
}
return result;
在编译时,当我们在MessageBodyMember
拥有流数组时,没有任何错误,直到服务在运行时通过我穿越Exception的方式将数组流(代码中的result
)传递给使用者时,一切都可以正常工作:
套接字连接已中止。 这可能是由于处理您的消息时出错,远程主机超出了接收超时或潜在的网络资源问题引起的。 本地套接字超时为“ 00:29:59.9895560”。
问题3:
为了实现上述场景, Contract
不得因向后兼容而更改,因此合同应具有像以前一样的消息正文流:
[MessageBodyMember]
public Stream Stream
{
get;
set;
}
但是我将zip部分的Stream
作为一个流写入到Stream
末尾,并且将在客户端服务器中读取每个流作为文件的拆分
解:
每个流的长度数字为4字节
每个流内容在其长度数字之后写入(4个字节后)
最后的流将是这样的
流=第1 Part1 len + part1 stream content + part2 len + part2 stream content + ....
1 Part1 len + part1 stream content + part2 len + part2 stream content + ....
任何评论和围绕答案的帮助将不胜感激。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.