I tried to create a custom BizTalk 2013 R2 (receive or send) pipeline that can unpack a xxx.GZ file that contains some txt files to a send port.
Here is what I have tried until now:
PS. I used .Net's IO GZip classes.
Created a BTS application, configured receive location and send port.
The receive location uses a custom pipeline that I have created, here is my code of the custom pipeline I tried:
public void Disassemble(IPipelineContext pc, IBaseMessage inmsg) { IBaseMessagePart bodyPart = inmsg.BodyPart; if (bodyPart != null) { Stream originalStream = bodyPart.GetOriginalDataStream(); if (originalStream != null) { using (GZipStream gZipInputStream = new GZipStream(new MemoryStream(originalStream.ReadByte()), CompressionMode.Decompress)) { MemoryStream memStream = new MemoryStream(); byte[] buffer = new Byte[1024]; int bytesRead = 1024; while (bytesRead != 0) { bytesRead = gZipInputStream.Read(buffer, 0, buffer.Length); gZipInputStream.CopyTo(buffer, 0); memStream.Write(buffer, 0, bytesRead); } IBaseMessage outMessage; outMessage = pc.GetMessageFactory().CreateMessage(); outMessage.AddPart("Body", pc.GetMessageFactory().CreateMessagePart(), true); memStream.Position = 0; outMessage.BodyPart.Data = memStream; outMessage.Context = PipelineUtil.CloneMessageContext(inmsg.Context); _msgs.Enqueue(outMessage); } } } }
This code seems to not work as I want. just send the GZ file without unpacking it to the send port. I use the implemented pipeline in the receive location port. Here is how it work: When BizTalk receive a GZ packed file on its receive location it just send the file to the send port that subscribe on this receive location. It seems like that the pipeline doesn't do any thing to the GZ stream. What it should do is to unpack the GZ file and send all the unpacked files to the send port, this points to a folder where the unpack files need to be placed.
I tried to google with no luck and the samples that exist seems to not work for me.
So can anyone help me or tell what I'm doing wrong in my code. I just want to implementing a C# custom BizTalk 2013 R2(receive or send) pipeline that can unpack a received GZ file, that contains some txt files, to a send port (point to a folder)?
Update:
As the Dissambler version didn't work I created a decode version.
Here is the decode code in the pipeline:
#region IComponent members
/// <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)
{
if (null == pc) throw new ArgumentNullException("pContext", "Pipeline context can not be null");
if (null == inmsg) throw new ArgumentNullException("pInMsg", "Input message can not be null");
IBaseMessagePart bodyPart = inmsg.BodyPart;
if (bodyPart != null)
{
GZipStream strm = new GZipStream(bodyPart.GetOriginalDataStream(), CompressionMode.Decompress);
bodyPart.Data = strm;
pc.ResourceTracker.AddResource(strm);
}
return inmsg;
}
#endregion
How can I get correct filename of each file in the GZip file? So when the message is sent to the send port, it should write the file with the correct filename.
It looks like you implemented the custom pipeline component as a Disassemble stage, it should actually be a Decode stage pipeline component for the following two reasons.
See MSDN Receive Pipelines
Update: With the update of you question it gets a bit trickier. If you have to split a message into multiple messages, the only stage you can do it in is the Disassemble stage. So you will have to go back to that version and debug it and work out why it does not execute the unzip.
There is a old code sample for a Zip Disassembler UnzipDisassembler - A custom pipeline component for BizTalk Server 2004 which is for a Zip file rather than a Gzip. But it follows the same sort of pattern. What you will also need is a method similar to GetNextEntry to publish a message and then parse the next file. It is at the outmsg creation stage that you can set the context properties such as filename.