我仍然无法提取MIME附件。请检查下面的MIME消息。我们从服务中收到的。
--MIMEBoundary_199ca6b7114b9acca5deb2047d25d5841d4afb7f68281379
Content-Type: application/xop+xml; charset=utf-8; type="text/xml"
Content-Transfer-Encoding: binary
Content-ID: <0.099ca6b7114b9acca5deb2047d25d5841d4afb7f68281379@apache.org>
<?xml version="1.0" encoding="utf-8"?><soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"><soapenv:Header><StateHeader xmlns="http://www.statemef.com/StateGatewayService"><MessageID>12345201704200009962</MessageID><RelatesTo>12345201704200009962</RelatesTo><Action>GetNewAcks</Action><Timestamp>2017-02-11T01:54:51.676-05:00</Timestamp><TestIndicator>T</TestIndicator></StateHeader></soapenv:Header><soapenv:Body><GetNewAcksResponse xmlns="http://www.statemef.com/StateGatewayService"><MoreAvailable>true</MoreAvailable><AcknowledgementListAttachmentMTOM><xop:Include xmlns:xop="http://www.w3.org/2004/08/xop/include" href="cid:299ca6b7114b9acca5deb2047d25d5841d4afb7f68281379@apache.org"></xop:Include></AcknowledgementListAttachmentMTOM></GetNewAcksResponse></soapenv:Body></soapenv:Envelope>
--MIMEBoundary_199ca6b7114b9acca5deb2047d25d5841d4afb7f68281379
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-ID: <299ca6b7114b9acca5deb2047d25d5841d4afb7f68281379@apache.org>
答案 0 :(得分:1)
步骤1:获取完整的 MIME流,即将Content-Type
参数定义为boundary
的{{1}}标头MIMEBoundary_199ca6b7114b9acca5deb2047d25d5841d4afb7f68281379
。没有它,你就是SOL。
如果您使用HttpWebRequest
之类的内容,请继续执行第2步。
第2步:按照MimeKit FAQ中的说明进行操作:
如何解析HTTP网络请求中的multipart / form-data?
由于像HttpWebResponse
这样的类负责解析HTTP头(包括Content-Type
头)并且只提供要使用的内容流,因此MimeKit提供了一种使用以下方法处理此问题的方法
MimeEntity上的两个静态方法:
public static MimeEntity Load (ParserOptions options, ContentType contentType, Stream content, CancellationToken cancellationToken = default (CancellationToken));
public static MimeEntity Load (ContentType contentType, Stream content, CancellationToken cancellationToken = default (CancellationToken));
以下是您可以使用这些方法的方法:
MimeEntity ParseMultipartFormData (HttpWebResponse response)
{
var contentType = ContentType.Parse (response.ContentType);
return MimeEntity.Load (contentType, response.GetResponseStream ());
}
拥有MimeEntity后,您可以将其转换为Multipart并枚举其中的附件,将内容保存为以下流:
int i = 1;
foreach (var attachment in multipart.OfType<MimePart> ()) {
string fileName = string.Format ("attachment.{0}.dat", i++);
using (var stream = File.Create (fileName))
attachment.ContentObject.DecodeTo (stream);
}
答案 1 :(得分:0)
问题仅显示响应正文。要解析它,您应该在响应标题前面添加。
例如,它应该如下所示:
MIME-Version: 1.0
content-type: multipart/related; type="application/xop+xml";start="<http://tempuri.org/0>";boundary="MIMEBoundary_someuniqueID";start-info="text/xml"
Server: Microsoft-IIS/10.0
X-Powered-By: ASP.NET
Content-Length:24371900
--MIMEBoundary_someuniqueID
Content-Type: application/xop+xml; charset=utf-8; type="text/xml" Content-Transfer-Encoding: binary
Content-ID: <http://tempuri.org/0>
<soap:Envelope>
<someWrapperElt>
<xop:Include href="cid:uri_of_content"></xop:Include>
</someWrapperElt>
</soap:Envelope>
--MIMEBoundary_someuniqueID
Content-Type: application/octet-stream
Content-Transfer-Encoding: binary
Content-ID: <uri_of_content>
...start.b1n@ry-content-here-etc.fckZ8990832d...
--MIMEBoundary_someuniqueID--
然后将整个响应转换为MemoryStream对象,并使用XmlDictionaryReader对其进行解析。
XmlDictionaryReader mtomReader = XmlDictionaryReader.CreateMtomReader(ms, Encoding.UTF8, XmlDictionaryReaderQuotas.Max);
也就是说,您现在可以从mtomReader对象中提取所需的值,包括附件。
答案 2 :(得分:0)
您可以在Github中执行解析器项目 WebResponseDerializer组件可以解析multipart soap消息
1)将soap body标签之间的xml消息复制到xml2charp站点并取出保存的对象。
2)采取响应流并如下调用。
Byte[] file = File.ReadAllBytes("..\\..\\Data\\ccc.xxx");
Stream stream = new MemoryStream(file);
WebResponseDerializer<SIGetImageResponse> deserilizer = new WebResponseDerializer<SIGetImageResponse>(stream);
SIGetImageResponse ddd = deserilizer.GetData();
foreach (var item in ddd.ResponseData.AttachmentDescriptor.Attachment)
{
String contentId = "<<" + item.ImageData.Include.Href + ">>";
contentId = contentId.Replace("%40", "@").Replace("cid:", "");
item.ImageData.Include.XopData = deserilizer.GetAttachment(contentId);
}