【问题标题】:Unable to Extract MTOM/XOP Attachment in C#无法在 C# 中提取 MTOM/XOP 附件
【发布时间】:2017-08-09 02:24:21
【问题描述】:

我仍然无法提取 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>

【问题讨论】:

    标签: c# mime format-conversion


    【解决方案1】:

    第 1 步:获取完整 MIME 流,即将Content-Type 标头定义为boundary 参数为MIMEBoundary_199ca6b7114b9acca5deb2047d25d5841d4afb7f68281379。没有它,你就是 SOL。

    如果您使用的是 HttpWebRequest 之类的内容,请继续执行第 2 步。

    第 2 步:按照 MimeKit FAQ 中的说明进行操作:

    如何解析来自 HTTP Web 请求的 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);
    }
    

    【讨论】:

    • 我在最新版本的 MimeKit 中找不到 .Parse() 方法? (2017 年 7 月)。因此我放弃了,只使用了 .NET 框架,使用 XmlDictionaryReader 查看我的答案。
    • 抱歉,应该是 MimeEntity.Load()
    • 大家好,只是想感谢您发布此内容...在找到此内容之前一直在扯头发!
    【解决方案2】:

    问题仅显示响应正文。要解析它,您应该在响应头之前添加。

    例如,它应该看起来像:

    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 对象中提取所需的值,包括附件。

    【讨论】:

      【解决方案3】:

      您可以在Github 获取解析器项目 WebResponseDerializer 组件可以解析多部分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);
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-08-02
        • 2012-01-23
        • 2016-11-30
        • 1970-01-01
        • 2023-03-12
        • 1970-01-01
        • 1970-01-01
        • 2013-08-11
        相关资源
        最近更新 更多