最好的方式来返回大文件分割压缩文件,流或字节数组WCF

本文关键字:文件 字节 WCF 数组 字节数 压缩 分割 方式 返回 | 更新日期: 2023-09-27 18:13:25

我已经返回zip文件流到客户端如下MessageContract:

[MessageContract]
public class ExportResult_C
{
    [MessageHeader]
    public PackedStudy_C[] PackedStudy
    {
        get;
        set;
    }
    [MessageBodyMember]
    public Stream Stream
    {
        get;
        set;
    }
}

当文件长度超过500mb时,我决定将其拆分为zip部分。

场景:

1-用户将调用导出方法返回ExportResult_C

2-如果请求的文件大于500mb,将其分割成更小的部分,每个部分必须有200MB的大小。

3-如果请求的文件小于500 MB,返回一个流的MessageContract

Desc:

为了向后兼容性,我决定将ExportResult_C更改为具有两个属性,一个名为Stream,它已经为文件小于500 MB而设计,另一个将是流数组,以容纳所有拆分zip,大小为200 MB。

问题:

1- MessageContract可以有另一个流的数组道具吗?

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

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

最好的方式来返回大文件分割压缩文件,流或字节数组WCF

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

问题1:

这是不可能有MessageBodyMember دeither Stream或任何其他类型,运行代码后,你可能会得到一个异常如下:

为了在MessageContract编程模型中使用Streams, 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)到消费者在运行时,顺便说一下,我越过异常,如:

socket连接被终止。这可能是由于处理消息时出现错误、远程主机超过接收超时或底层网络资源问题造成的。本地套接字超时'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 + ....

任何关于答案的评论和帮助都将是非常感谢的。