将大文件作为拆分zip文件返回的最佳方法,Stream或Byte数组WCF

时间:2016-10-18 08:35:59

标签: c# .net arrays wcf stream

我已经将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。

问题:

1- MessageContract是否可以拥有另一个流的数组支持?

2-如果没有,是否可以将Stream道具更改为Stream类型的数组?

3-或者为了实现上述场景,我必须完全改变合同,或者有更好的想法(在吞吐量和向后兼容性方面)?

1 个答案:

答案 0 :(得分:0)

我想分享调查结果和我的解决方案,将大文件作为流传递给客户消费者:

问题1:

这不可能MessageBodyMemberدStream或任何其他类型,在运行代码后您可能会遇到以下异常:

  

为了将Streams与MessageContract编程模型一起使用,yourMessageContract类型必须具有MessageBodyMember属性的单个成员,并且成员类型必须为Stream。

问题2:

我将合同更改为拥有名为Stream的道具成员,就像我想要的那样,Streams是一个流数组:

 [MessageBodyMember]
    public Stream[] Streams 
    {
        get;
        set;
    }

我的代码片段将大文件拆分为zip部分,并将每个部分的流转换为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中有数组流时没有任何错误,一切正常,直到服务在运行时将数组流(代码中的result)传递给消费者,我越过Exception的方式如下:

  

套接字连接已中止。这可能是由于处理消息的错误或远程主机超出接收超时或基础网络资源问题引起的。本地套接字超时为'00:29:59.9895560'。

问题3:

要实现上述方案,Contract不应更改为向后兼容性,因此合同具有与之前类似的邮件正文流:

  [MessageBodyMember]
public Stream Stream
{
    get;
    set;
}

但我打算将zip部分的流写入Stream的末尾作为一个流,并且在客户端 - 服务器中将读取每个流作为文件分割

溶液:

  • 每个流的长度编号的4个字节

  • 每个流内容在其长度编号后写入(4字节后)

在结尾流将是这样的

Stream = Part1 len + part1 stream content + part2 len + part2 stream content + ....

任何有关答案的评论和帮助都会得到真正的赞赏。