Biztalk Server zip unzip pipeline component Development
Biztalk Server zip unzip pipeline component Development
最近有个B2B的项目涉及和其他合作伙伴(partner)作数据传输,我们这边使用的开发平台(platform)是Biztalk Server 2006,数据传输管道(channel)采用window server 2003的MSMQ,但是由于MSMQ本身存在单个消息有4M限制的问题,虽软Biztalk Server 2006自带的MSMQ Adapter已经对大消息(Large Data)的支持,提供了[Support segmentation] if true , message larger than 4095KB(approximately 4MB) will be segmented,说明当发送单个报文实例(Instance)超过4MB的时候可以在发送至MSMQ对列的时候进行分割成几个小的消息发送,这些被分割的消息之间通过Message. CorrelationId进行关联具体的做法可以参考《MSMQ消息大于4MB限制的解决办法》采用对消息进行分割的做法会对接收消息需要作特定的判断,相对于对报文压缩来得比较简单;
下面介绍一下如何通过对Biztalk Pipeline的二次开发实现对报文进行压缩/解压得实现;
功能描述:
1/将Biztalk 流程(Orchestration)出来的消息在发送端口通过加载pipeline组件实现将消息以zip的方式进行压缩(zip可以对Xml,txt文档的压缩比达到10:1)
2/将接收的zip文件(支持包含多个文件批处理(batch))进行压缩后进入Biztalk流程(Orchestration)处理;
具体实现:
要实现对Biztalk Pipeline的开发对如下接口[Microsoft.BizTalk.Component.Interop.IComponent,IBaseComponent, IPersistPropertyBag, IComponentUI]做实现,好在现在网上提供pipeline component wizrad:http://www.gotdotnet.com/Workspaces/Workspace.aspx?id=1d4f7d6b-7d27-4f05-a8ee-48cfcd5abf4a 可以下载到pipeline开发向导
实现对文件进行压缩/解压需要的[ICSharpCode.SharpZipLib.dll]目前版本0.85相当稳定;下载地址:http://www.icsharpcode.net/OpenSource/SharpZipLib/ 具体方法请查看版本
通过安装pipeline component wizrad之后就可以在vs.net中创建你的pipeline component组件了。CategoryTypes表示该组件可以加载到pipline的什么位置CategoryTypes.CATID_Any表示任何位置都可以放;
[ComponentCategory(CategoryTypes.CATID_PipelineComponent)]
[System.Runtime.InteropServices.Guid("62656b9b-7d69-407d-b71f-d3c0415c82af")]
[ComponentCategory(CategoryTypes.CATID_DisassemblingParser)]
public class UnzipDisassemblerComponent : Microsoft.BizTalk.Component.Interop.IDisassemblerComponent, IBaseComponent, IPersistPropertyBag, IComponentUI
{
private System.Resources.ResourceManager resourceManager = new System.Resources.ResourceManager("Execution.BizTalk.Common.Pipelines.UnzipDisassemblerPipeline", Assembly.GetExecutingAssembly());
#region IBaseComponent members
下面是对Biztalk消息进行解压/压缩的代码实现。
/// <summary>解压2

3
/// called by the messaging engine when a new message arrives4

5
/// </summary>6

7
/// <param name="pc">the pipeline context</param>8

9
/// <param name="inmsg">the actual message</param>10

11
public void Disassemble(Microsoft.BizTalk.Component.Interop.IPipelineContext pc, Microsoft.BizTalk.Message.Interop.IBaseMessage inmsg)12

13
{14

15
16

17
Stream strmZipFile;18

19
20

21
IBaseMessagePart msgPart;22

23
msgPart = inmsg.BodyPart;24

25
strmZipFile = msgPart.GetOriginalDataStream();26

27
28

29
ZipInputStream oZipStream = new ZipInputStream(strmZipFile);30

31
if (!string.IsNullOrEmpty(mPassword))32

33
oZipStream.Password = mPassword;34

35
36

37
try38

39
{40

41
42

43
ZipEntry sEntry = oZipStream.GetNextEntry();44

45
while (sEntry != null )46

47
{48

49
if (sEntry.IsDirectory)50

51
{52

53
sEntry = oZipStream.GetNextEntry();54

55
continue;56

57
}58

59
60

61
MemoryStream strmMem = new MemoryStream();62

63
byte[] buffer = new byte[4096];64

65
int count = 0;66

67
while ((count = oZipStream.Read(buffer, 0, buffer.Length)) != 0)68

69
strmMem.Write(buffer, 0, count);70

71
72

73
strmMem.Seek(0, SeekOrigin.Begin);74

75
msgPart.Data = strmMem;76

77
78

79
IBaseMessage outMsg;80

81
82

83
outMsg = pc.GetMessageFactory().CreateMessage();84

85
outMsg.AddPart("Body", pc.GetMessageFactory().CreateMessagePart(), true);86

87
outMsg.BodyPart.Data = strmMem;88

89
90

91
for (int iProp = 0; iProp < inmsg.Context.CountProperties; iProp++)92

93
{94

95
string strName;96

97
string strNSpace;98

99
100

101
object val = inmsg.Context.ReadAt(iProp, out strName, out strNSpace);102

103
// If the property has been promoted, respect the settings104

105
if (inmsg.Context.IsPromoted(strName, strNSpace))106

107
outMsg.Context.Promote(strName, strNSpace, val);108

109
else110

111
outMsg.Context.Write(strName, strNSpace, val);112

113
}114

115
116

117
if (this.Namespace != null && this.RootElementName != null)118

119
{120

121
string messageType = string.Format("{0}#{1}", this.Namespace, this.RootElementName);122

123
outMsg.Context.Promote("MessageType", "http://schemas.microsoft.com/BizTalk/2003/system-properties", messageType);124

125
}126

127
_msgs.Enqueue(outMsg);128

129
sEntry = oZipStream.GetNextEntry();130

131
}132

133
}134

135
catch (Exception ex)136

137
{138

139
Debug.Write(ex.Message + Environment.NewLine + ex.StackTrace);140

141
throw;142

143
}144

145
146

147
}148

149
150

151
//压缩消息152

153
/// <summary>154

155
/// Implements IComponent.Execute method.156

157
/// </summary>158

159
/// <param name="pc">Pipeline context</param>160

161
/// <param name="inmsg">Input message</param>162

163
/// <returns>Original input message</returns>164

165
/// <remarks>166

167
/// IComponent.Execute method is used to initiate168

169
/// the processing of the message in this pipeline component.170

171
/// </remarks>172

173
public Microsoft.BizTalk.Message.Interop.IBaseMessage Execute(174

175
Microsoft.BizTalk.Component.Interop.IPipelineContext pc, 176

177
Microsoft.BizTalk.Message.Interop.IBaseMessage inmsg)178

179
{180

181
// 182

183
// TODO: implement component logic184

185
186

187
//string[] filenames = Directory.GetFiles(args[0]);188

189
byte[] buffer = new byte[4096];190

191
string fileName = string.Empty;192

193
Stream strmZipFile=new MemoryStream();194

195
Stream strmOriginFile;196

197
Stream strmZip; ;198

199
IBaseMessagePart msgPart;200

201
msgPart = inmsg.BodyPart;202

203
strmOriginFile = msgPart.GetOriginalDataStream();204

205
try206

207
{208

209
210

211
using (ZipOutputStream s = new ZipOutputStream(strmZipFile))212

213
{214

215
216

217
218

219
s.SetLevel(9); // 0 - store only to 9 - means best compression220

221
//fileName = Guid.NewGuid().ToString() + "." + this.extension;222

223
fileName = inmsg.Context.Read("ReceivedFileName", "http://schemas.microsoft.com/BizTalk/2003/" + messageContext.InboundTransportType.ToLower() + "-properties").ToString();224

225
s.Password = this.password;226

227
ZipEntry entry = new ZipEntry(fileName);228

229
s.PutNextEntry(entry);230

231
StreamUtils.Copy(strmOriginFile, s, buffer);232

233
s.Finish();234

235
strmZip = new MemoryStream();236

237
strmZipFile.Seek(0, SeekOrigin.Begin);238

239
StreamUtils.Copy(strmZipFile, strmZip, buffer);240

241
strmZip.Seek(0, SeekOrigin.Begin);242

243
s.Close();244

245
246

247
248

249
}250

251
252

253
msgPart.Data = strmZip;254

255
pc.ResourceTracker.AddResource(strmZip);256

257
// this way, it's a passthrough pipeline component258

259
260

261
return inmsg;262

263
}264

265
catch (Exception e)266

267
{268

269
Debug.WriteLine("[zipAssember] " + e.Message);270

271
throw e;272

273
}274

275
}276




浙公网安备 33010602011771号