Best way to return large file as split zip files,Stream or Byte array WCF

后端 未结 1 790
梦谈多话
梦谈多话 2021-01-17 01:48

I have already return zip file stream to client as the following MessageContract:

[MessageContract]
public class ExportResult_C
{
    [MessageHe         


        
相关标签:
1条回答
  • 2021-01-17 02:07

    I want to share the result of my investigation and my solution to pass big file as stream to client consumer:

    Question 1:

    this is not possible to have MessageBodyMember دeither Stream or any other type, after running code you may got an Exception as following:

    In order to use Streams with the MessageContract programming model, the type yourMessageContract must have a single member with MessageBodyMember attribute and the member type must be Stream.

    Question 2:

    I changed the contract to have a prop member named Stream like what I was wanted, the Streams is array of stream:

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

    my piece of code to split big file to parts of zip and make stream of each part into Streams like:

     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;
    

    At the compile time there is no any error when we have array of stream in MessageBodyMember, everything works fine until the service is passing array stream (result in code) to consumer at runtime, by the way I cross the Exception like :

    The socket connection was aborted. This could be caused by an error processing your message or a receive timeout being exceeded by the remote host, or an underlying network resource issue. Local socket timeout was '00:29:59.9895560'.

    Question 3:

    To implement the mentioned scenario the Contract should not change for Backward-Compatibility so the contract have a message body stream like before:

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

    but I am going to write stream of the zip part to end of Stream as one stream and in client-server will be read an split each stream as file

    solution:

    • 4 Byte for length number of each stream

    • each stream content write after it's length number(after 4 byte)

    at the end stream will be something like this

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

    any comment and help around the answer would be truly appreciated.

    0 讨论(0)
提交回复
热议问题