Wednesday, September 23, 2009

Zip - pipeline component

Recently I got a requirement from my client to Integrate BizTalk with the Amazon cloud, Basically we have to send notification message to a FTP Location in Amazon.
As Amazon charges based upon the pay per usage, we had a requirement to compress the file before sending to the Amazon location to reduce the cost..

I tried to search for Pipeline component, Most of the pipeline component comes with the cost (
http://www.nsoftware.com/products/biztalk/default.aspx). So I decided to create my own, with the help of open source .Net Library which is available at http://www.icsharpcode.net/OpenSource/SharpZipLib/
About the component

ZipFile is a pipeline component which Archives the file in encoding stage of the send Pipeline. This is a generalized component, which can be used wherever required.
The ZipFile Name based upon the Adapter Configuration.
File Name inside the Archieve If the "OutboundTransportLocation” (
http://schemas.microsoft.com/BizTalk/2003/system-properties) has value the file name will be extracted and it will be the same name as Zip File . Else MessageID Property will be used as file name inside Zip.
The File Extension for the File inside the zip is configurable "FileExtension"
Steps

On receiving the message, the component will

  • Read the body of the message (Which is a stream) to the Zip function and the message name
  • Zip the stream, Update the Name of the Zipped File and return as a memory stream.
  • Process the memory stream to update the message body and return as message

Code snippet




public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)
{
try
{
// Name of the File inside the Zip Starts Here
String MessageId ="";
String Extension = "." + _FileExtension;

MessageId = pInMsg.Context.Read("OutboundTransportLocation", "http://schemas.microsoft.com/BizTalk/2003/system-properties").ToString() ;

if (MessageId == "")
{
MessageId = pInMsg.MessageID + Extension;
}
else
{
try
{
//From OutboundTransportLocation
MessageId = MessageId.Remove(0, MessageId.LastIndexOf(@"/") + 1);
MessageId = MessageId.Remove(MessageId.LastIndexOf(@"."));
MessageId = MessageId + Extension;
}
catch
{
MessageId = pInMsg.MessageID + Extension;
}

}

// Name of the File inside the Zip Ends Here

MemoryStream outmsg = new MemoryStream();

IBaseMessagePart bodyPart = pInMsg.BodyPart;
if (bodyPart != null)
{
ZipingTheStream(bodyPart.Data, outmsg, MessageId);
}

return CreateNewMessage(pContext, pInMsg, outmsg);

}
catch (Exception ex)
{
throw new System.ApplicationException(ex.Message);
}
}

///
/// Helper function that creates a new message and copies all parts
/// and their properties. Copies new stream to current message
///

/// Context
/// Orginal BTS message
/// Contains contents of message to create
///
public static IBaseMessage CreateNewMessage(IPipelineContext pipelineContext,
IBaseMessage message, Stream streamOut)
{
if (null == pipelineContext)
throw new ArgumentNullException("pipelineContext");
if (null == message)
throw new ArgumentNullException("message");
if (null == streamOut)
throw new ArgumentNullException("streamOut");

try
{
ICloneable c = (ICloneable)message;
IBaseMessage outMsg = (IBaseMessage)c.Clone();
streamOut.Position = 0;
outMsg.BodyPart.Data = streamOut;

// Clean up resources
pipelineContext.ResourceTracker.AddResource(outMsg.BodyPart.Data);

return outMsg;
}
catch (Exception ex)
{
//EventLog.WriteEntry(ex.Source , ex.message);
throw ex;
}
}

public static void ZipingTheStream(Stream InMsgBody, Stream ZipStream, String FileName)
{
try
{
ZipOutputStream ZipOutStream = new ZipOutputStream(ZipStream);
ZipOutStream.SetLevel(9);

ZipEntry InMsgBodyEntry = new ZipEntry(ZipEntry.CleanName(FileName));
InMsgBodyEntry.DateTime = DateTime.Now;
InMsgBodyEntry.Size = InMsgBody.Length;
ZipOutStream.PutNextEntry(InMsgBodyEntry);
byte[] BufferTransfer = new byte[1024 * 1024];

int Filebyte;
Stream FileTobeZipped = InMsgBody;
for (; ; )
{
//we copy the file to the Zip stream, block after block
Filebyte = FileTobeZipped.Read(BufferTransfer, 0, 1024 * 1024);
if (Filebyte == 0) break;
ZipOutStream.Write(BufferTransfer, 0, Filebyte);
}
//ZipOutStream.

ZipOutStream.Finish();
//ZipOutStream.Close();


}
catch (Exception ex)
{
throw ex;
}
}

No comments:

Post a Comment