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消息进行解压/压缩的代码实现。
1
/**//// <summary>解压
2
3
/// called by the messaging engine when a new message arrives
4
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
try
38
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 settings
104
105
if (inmsg.Context.IsPromoted(strName, strNSpace))
106
107
outMsg.Context.Promote(strName, strNSpace, val);
108
109
else
110
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 initiate
168
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 logic
184
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
try
206
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 compression
220
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 component
258
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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix