【问题标题】:How do you embed binary data in XML?如何在 XML 中嵌入二进制数据?
【发布时间】:2010-09-06 09:37:42
【问题描述】:

我有两个用 Java 编写的应用程序,它们通过网络使用 XML 消息相互通信。我在接收端使用 SAX 解析器从消息中取回数据。要求之一是在 XML 消息中嵌入二进制数据,但 SAX 不喜欢这样。有谁知道怎么做?

更新:我使用 apache commons codec libraryBase64 类进行了这项工作,以防其他人尝试类似的事情。

【问题讨论】:

    标签: java xml binary binary-data


    【解决方案1】:

    虽然其他答案大多都很好,但您可以尝试另一种更节省空间的编码方法,例如 yEnc。 (yEnc wikipedia link) 使用 yEnc 还可以“开箱即用”地获得校验和功能。阅读下面的链接。当然,因为 XML 没有原生 yEnc 类型,所以您的 XML 模式应该更新以正确描述编码节点。

    为什么:由于编码策略 base64/63,uuencode 等。编码将您需要存储和传输的数据量(开销)增加了大约 40%(与 yEnc 的 1-2% 相比)。根据您编码的内容,40% 的开销可能/成为问题。


    yEnc - 维基百科摘要: https://en.wikipedia.org/wiki/YEnc yEnc 是一种二进制到文本的编码方案,用于在 Usenet 上的消息中或通过电子邮件传输二进制文件。 ... 与以前的编码方法(例如 uuencode 和 Base64)相比,yEnc 的另一个优势是包含 CRC 校验和,以验证解码后的文件是否已完整交付。 ‎

    【讨论】:

    • @Jamine 你还有其他选择吗?
    • 杰米,如果再做一些工作,这可能是一个不错的答案。我删除了我的 -1,如果你付出一些努力,我会 +1...如果你跟进,请标记我。
    • 杰米,n/m。我更新了你的答案,并 +1ed,希望能提供你最初想要传达的信息。一定要看看,也许在你认为合适的时候进行更新。 (我已经有一段时间没有在 SO 上活跃了。研究和编辑答案很有趣。我 +1 是因为在此过程中我学到了一些新东西,这就是它的全部意义......?干杯。)
    • 当可预测/固定开销至关重要时,escapeless 可能是 yEnc 的替代方案。
    【解决方案2】:

    如果您可以控制 XML 格式,则应该彻底解决问题。与其附加二进制 XML,不如考虑如何封装包含多个部分的文档,其中一个部分包含 XML。

    对此的传统解决方案是存档(例如 tar)。但是,如果您想以基于文本的格式保存您的附件文档,或者如果您无法访问文件归档库,那么还有一个在电子邮件和 HTTP 中大量使用的标准化方案,即 multipart/* MIME 和 @ 987654322@.

    例如,如果您的服务器通过 HTTP 进行通信,并且您希望发送一个多部分文档,主要是一个 XML 文档,它引用二进制数据,那么 HTTP 通信可能如下所示:

    POST / HTTP/1.1
    Content-Type: multipart/related; boundary="qd43hdi34udh34id344"
    ... other headers elided ...
    
    --qd43hdi34udh34id344
    Content-Type: application/xml
    
    <myxml>
        <data href="cid:data.bin"/>
    </myxml>
    --qd43hdi34udh34id344
    Content-Id: <data.bin>
    Content-type: application/octet-stream
    Content-Transfer-Encoding: binary
    
    ... binary data ...
    --qd43hdi34udh34id344--
    

    如上例所示,XML 使用 cid URI 方案引用封闭多部分中的二进制数据,该方案是 Content-Id 标头的标识符。该方案的开销只是 MIME 标头。类似的方案也可用于 HTTP 响应。当然,在 HTTP 协议中,您还可以选择将多部分文档发送到单独的请求/响应中。

    如果您想避免将数据包装在多部分中,请使用数据 URI:

    <myxml>
        <data href="data:application/something;charset=utf-8;base64,dGVzdGRhdGE="/>
    </myxml>
    

    但这有 base64 开销。

    【讨论】:

      【解决方案3】:

      Base64 开销为 33%。

      BaseXML 用于 XML1.0 开销仅为 20%。但它不是一个标准,只有一个 C 实现。如果您担心数据大小,请查看它。但是请注意,浏览器倾向于实现压缩,因此不需要它。

      我在这个帖子讨论后开发了它:Encoding binary data within XML : alternatives to base64

      【讨论】:

        【解决方案4】:

        上周我遇到了这个问题。我必须序列化一个 PDF 文件并将其在 XML 文件中发送到服务器。

        如果您使用的是 .NET,则可以将二进制文件直接转换为 base64 字符串并将其粘贴到 XML 元素中。

        string base64 = Convert.ToBase64String(File.ReadAllBytes(fileName));
        

        或者,在 XmlWriter 对象中内置了一个方法。在我的特殊情况下,我必须包含 Microsoft 的数据类型命名空间:

        StringBuilder sb = new StringBuilder();
        System.Xml.XmlWriter xw = XmlWriter.Create(sb);
        xw.WriteStartElement("doc");
        xw.WriteStartElement("serialized_binary");
        xw.WriteAttributeString("types", "dt", "urn:schemas-microsoft-com:datatypes", "bin.base64");
        byte[] b = File.ReadAllBytes(fileName);
        xw.WriteBase64(b, 0, b.Length);
        xw.WriteEndElement();
        xw.WriteEndElement();
        string abc = sb.ToString();
        

        字符串 abc 看起来像这样:

        <?xml version="1.0" encoding="utf-16"?>
        <doc>
            <serialized_binary types:dt="bin.base64" xmlns:types="urn:schemas-microsoft-com:datatypes">
                JVBERi0xLjMKJaqrrK0KNCAwIG9iago8PCAvVHlwZSAvSW5mbw...(plus lots more)
            </serialized_binary>
        </doc>
        

        【讨论】:

        • 最佳答案,因为我可以从中复制/粘贴 Convert.ToBase64String
        【解决方案5】:

        任何binary-to-text encoding 都可以解决问题。我使用类似的东西

        <data encoding="yEnc>
        <![CDATA[ encoded binary data ]]>
        </data>
        

        【讨论】:

          【解决方案6】:

          您可以使用 base64 对二进制数据进行编码并将其放入 Base64 元素中;下面的文章是关于这个主题的一篇很好的文章。

          Handling Binary Data in XML Documents

          【讨论】:

            【解决方案7】:

            你也可以Uuencode你原来的二进制数据。这种格式有点旧,但它与 base63 编码的作用相同。

            【讨论】:

            • * base63 编码
            【解决方案8】:

            Base64 确实是正确的答案,但 CDATA 不是,这基本上是在说:“这可能是任何东西”,但它必须 只是任何东西,它必须是 Base64 编码的二进制数据。 XML Schema 定义了您可以在 xsd 中使用的 Base 64 binary as a primitive datatype

            【讨论】:

            • 额外提到xs:base64Binary数据类型,这是正确的使用类型。
            【解决方案9】:

            XML 用途广泛……

            <DATA>
              <BINARY>
                <BIT index="0">0</BIT>
                <BIT index="1">0</BIT>
                <BIT index="2">1</BIT>
                ...
                <BIT index="n">1</BIT>
              </BINARY>
            </DATA>
            

            XML 就像暴力一样 - 如果它不能解决您的问题,那么您就没有充分利用它。

            编辑:

            顺便说一句:Base64 + CDATA 可能是最好的解决方案

            (EDIT2:
            谁升级我,也请升级真正的答案。我们不希望任何可怜的灵魂来到这里并实际实施我的方法,因为它在 SO 上排名最高,对吧?)

            【讨论】:

            • 如果你是认真的,这就是对 XML 的完全可耻的使用。如果你不是,不写高层次思考低层次的初学者怎么会知道?
            • 我觉得这很有趣。但是,是的,再一次,使用实际的 base64 数据类型是要走的路。 CData 太笼统了。
            • 我认为它的描述性不够——也许应该使用“BINARYDIGIT”而不是缩写“BIT”? ;-)
            • 哇。这将使平均千字节范围的文件大 230 倍 :)
            • 哦,看在他妈的份上。这是个笑话。我做了什么?!:thedailywtf.com/Articles/The-HumanReadable-Encryption-Key.aspx
            【解决方案10】:

            我通常使用MIME Base64URL encoding 对二进制数据进行编码。

            【讨论】:

              【解决方案11】:

              尝试使用 Base64 编码/解码您的二进制数据。还要查看 CDATA 部分

              【讨论】:

                【解决方案12】:

                也许将它们编码成一个已知的集合——比如 base 64 是一种流行的选择。

                【讨论】:

                  猜你喜欢
                  • 2011-05-25
                  • 2013-06-18
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-02-13
                  • 2023-03-12
                  相关资源
                  最近更新 更多