Q:

Multiple Files into One Zip Archive

I have a scenario where i receive multiple files which i need to Compress in one Zip file , 
I did aggregate design pattern in biztalk which calls the below pipeline , but the below pipeline which i wrote just zips one file , 
using Ionic.Zip;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.BizTalk.Message.Interop;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BizTalkLive.Zip
{
    [ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
    [System.Runtime.InteropServices.Guid("6F31BA70-F87E-4150-B5A5-2803D00C4FA0")]
    [ComponentCategory(CategoryTypes.CATID_Encoder)]
    public class Zip:IBaseComponent,IPersistPropertyBag,IComponentUI,IComponent
    {
        #region IBaseComponent
        public string Description
        {
            get
            {
                return "Pipeline component used to zip a message";
            }
        }
        public string Name
        {
            get
            {
                return "ZipEncoder";
            }
        }
        public string Version
        {
            get
            {
                return "1.0.0.0";
            }
        }
        #endregion

        #region IPersistPropertyBag
        /// <summary>
        /// Gets class ID of component for usage from unmanaged code.
        /// </summary>
        /// <param name="classid">
        /// Class ID of the component
        /// </param>
        public void GetClassID(out System.Guid classid)
        {
            classid = new System.Guid("6F31BA70-F87E-4150-B5A5-2803D00C4FA0");
        }

        /// <summary>
        /// not implemented
        /// </summary>
        public void InitNew()
        {
        }

        /// <summary>
        /// Loads configuration properties for the component
        /// </summary>
        /// <param name="pb">Configuration property bag</param>
        /// <param name="errlog">Error status</param>
        public virtual void Load(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, int errlog)
        {
        }

        /// <summary>
        /// Saves the current component configuration into the property bag
        /// </summary>
        /// <param name="pb">Configuration property bag</param>
        /// <param name="fClearDirty">not used</param>
        /// <param name="fSaveAllProperties">not used</param>
        public virtual void Save(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, bool fClearDirty, bool fSaveAllProperties)
        {
        }

        #region utility functionality
        /// <summary>
        /// Reads property value from property bag
        /// </summary>
        /// <param name="pb">Property bag</param>
        /// <param name="propName">Name of property</param>
        /// <returns>Value of the property</returns>
        private object ReadPropertyBag(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, string propName)
        {
            object val = null;
            try
            {
                pb.Read(propName, out val, 0);
            }
            catch (System.ArgumentException)
            {
                return val;
            }
            catch (System.Exception e)
            {
                throw new System.ApplicationException(e.Message);
            }
            return val;
        }

        /// <summary>
        /// Writes property values into a property bag.
        /// </summary>
        /// <param name="pb">Property bag.</param>
        /// <param name="propName">Name of property.</param>
        /// <param name="val">Value of property.</param>
        private void WritePropertyBag(Microsoft.BizTalk.Component.Interop.IPropertyBag pb, string propName, object val)
        {
            try
            {
                pb.Write(propName, ref val);
            }
            catch (System.Exception e)
            {
                throw new System.ApplicationException(e.Message);
            }
        }
        #endregion

        #endregion

        #region IComponentUI
        public IntPtr Icon
        {
            get
            {
                return IntPtr.Zero;
            }
        }
        public IEnumerator Validate(object projectystem)
        {
            return null;
        }
        #endregion

        #region IComponent
        /// <summary>
        /// Implements IComponent.Execute method.
        /// </summary>
        /// <param name="pc">Pipeline context</param>
        /// <param name="inmsg">Input message</param>
        /// <returns>Original input message</returns>
        /// <remarks>
        /// IComponent.Execute method is used to initiate
        /// the processing of the message in this pipeline component.
        /// </remarks>
        public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute(Microsoft.BizTalk.Component.Interop.IPipelineContext pc, Microsoft.BizTalk.Message.Interop.IBaseMessage inmsg)
        {

            IBaseMessageContext context = inmsg.Context;
            string fileName = string.Empty;
            object obj = context.Read("ReceivedFileName", "http://schemas.microsoft.com/BizTalk/2003/file-properties");
            fileName = ((string)obj).Substring(((string)obj).LastIndexOf("\\") + 1);

            Byte[] TextFileBytes = null;
            IBaseMessagePart msgBodyPart = inmsg.BodyPart;
            //Creating outMessage
            IBaseMessage outMessage;
            outMessage = pc.GetMessageFactory().CreateMessage();

            if (msgBodyPart != null)
            {
                outMessage.Context = PipelineUtil.CloneMessageContext(inmsg.Context);
                Stream msgBodyPartStream = msgBodyPart.GetOriginalDataStream();
                TextFileBytes = ReadToEnd(msgBodyPartStream);
                outMessage.AddPart("Body", pc.GetMessageFactory().CreateMessagePart(), true);

                IDictionary<string, Byte[]> lst = new Dictionary<string, Byte[]>();

                lst.Add(fileName, TextFileBytes);

                MemoryStream ms;

                using (ZipFile zip = new ZipFile())
                {
                    foreach (KeyValuePair<string, Byte[]> item in (IDictionary<string, Byte[]>)lst)
                    {
                        zip.AddEntry(item.Key, item.Value);

                    }
                    ms = new MemoryStream();
                    ms.Seek(0, SeekOrigin.Begin);
                    zip.Save(ms);
                }

                ms.Position = 0;
                outMessage.BodyPart.Data = ms;
                outMessage.Context.Promote("ReceivedFileName", "http://schemas.microsoft.com/BizTalk/2003/file-properties", fileName.Substring(0,fileName.IndexOf(".")));
            }
            return outMessage;
        }

        public static byte[] ReadToEnd(System.IO.Stream stream)
        {
            long originalPosition = 0;

            if (stream.CanSeek)
            {
                originalPosition = stream.Position;
                stream.Position = 0;
            }

            try
            {
                byte[] readBuffer = new byte[4096];

                int totalBytesRead = 0;
                int bytesRead;

                while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
                {
                    totalBytesRead += bytesRead;

                    if (totalBytesRead == readBuffer.Length)
                    {
                        int nextByte = stream.ReadByte();
                        if (nextByte != -1)
                        {
                            byte[] temp = new byte[readBuffer.Length * 2];
                            Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
                            Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
                            readBuffer = temp;
                            totalBytesRead++;
                        }
                    }
                }

                byte[] buffer = readBuffer;
                if (readBuffer.Length != totalBytesRead)
                {
                    buffer = new byte[totalBytesRead];
                    Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
                }
                return buffer;
            }
            finally
            {
                if (stream.CanSeek)
                {
                    stream.Position = originalPosition;
                }
            }
        }

        #endregion
    }
}

I want to create custom pipeline component which i can use in assembler stage where i can aggregate all the message and zip it in one archive

A:

You need use ZipArchive.
Example below shows the one of case its using: 
var fileUrls = new[]
{
    new Uri("https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/media/image3.5.png"),
    new Uri("https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/media/image4.png"),
    new Uri("https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/media/image6.png")
};

var downloadResults = fileUrls
    .Select(uri => (uri: uri, response: HttpClientFactory.Create().SendAsync(new HttpRequestMessage(HttpMethod.Get, uri))))
    .ToArray();

await Task.WhenAll(downloadResults.Select(v => v.response));

using (var ms = new MemoryStream())
{
    using (var archive = new ZipArchive(ms, ZipArchiveMode.Create, true))
    {
        foreach (var download in downloadResults)
        {
            var entry = archive.CreateEntry(download.uri.Segments.Last(), CompressionLevel.Fastest);

            using (var zipStream = entry.Open())
            {
                var data = await download.response.Result.Content.ReadAsByteArrayAsync();

                zipStream.Write(data, 0, data.Length);
            }
        }
    }

    using (var fileStream = File.Create($"{DateTime.Now.Ticks}.zip"))
    {
        await fileStream.WriteAsync(ms.ToArray());
    }
}

