在Java中,我正在轮询WebSphere MQ消息队列,期待一条完全由XML组成的“STRING格式”消息。此XML的一部分将包含文件附件的字节(任何格式:pdf,图像等),然后将其转换为blob以便在Oracle Db中存储并在以后检索。
我遇到的问题是,我的Db中发送的示例文件的已知大小最终会有不同的大小。我没有在字节中添加任何内容(据我所知),在收到消息后,大小似乎直接变大了。我无法确定我是否以某种方式在检索时添加信息,转换自bytes
- > String
,或者当发件人填充邮件时,如果在前端发生这种情况。
检索邮件的代码:
inboundmsg = new MQMessage();
inboundmsg = getMQMsg(FrontIncomingQueue, gmo);
strLen = inboundmsg.getMessageLength();
strData = new byte[strLen];
ibm_id = inboundmsg.messageId;
inboundmsg.readFully(strData);
inboundmsgContents = new String(strData);
我看到一个已知大小为21K的文件变为28K。同事建议charset /编码可能是问题。我没有在上面的String
的构造函数调用中指定字符集,也没有在从字符串转换回来时对getBytes
的任何调用中指定(对于其他不相关的用途)。我的默认字符集是ISO-8859-1。在与正在启动邮件传输的供应商交谈时,我问她正在使用什么字符集。她的回复:
“我在C#中使用File.WriteAllBytes方法 - 我将它传递给我的文件的路径并将其写入byte []。我在MSDN上找不到有关该函数使用的编码的任何文档。方法创建一个字节数组,从我今天早上在网上看到的没有编码,它只是一个没有编码的8位无符号二进制数据序列。“
另一位同事建议也许MQ字符集是罪魁祸首,但我对文档的阅读表明MQ字符集只会影响readString
,readLine
和&的行为。 writeString
。
如果我完全绕过MQ,并使用文件输入流和本地文件填充字节数组,则文件大小一直保留到Db存储,因此这肯定会在消息传输时或消息传输期间发生。
答案 0 :(得分:1)
问题的措辞明显存在问题。您描述了包含任意二进制数据的有效负载,并尝试将其作为字符串进行处理。这两件事是相互排斥的。
供应商不提供有效的XML似乎很复杂。例如,考虑附件:
<PdfBytes>iVBORw0KGgoAAAANS … AAAAASUVORK5CYII=</PdfBytes>
如果附件合法地包含任何XML特殊字符,例如<
或>
,则结果是无效的XML。如果它包含空字节,则一些解析器假定它们已到达文本的末尾并停止在那里解析。这就是为什么您通常会看到XML中的任何附件要么转换为Base64进行传输,要么转换为十六进制。
供应商描述了编写原始二进制数据,这表明您接收的内容包含非字符串字符,因此不应作为字符串数据发送。如果她描述了某种类型的转换,这将使附件符合XML,那么字符串将是合适的。
有趣的是,Base64编码导致有效载荷比原始版本大1.33倍。巧合21k * 1.3 = 28k
?有人会认为收到的实际上是Base64格式的二进制有效载荷。实际上 可以作为字符串进行解析,并说明文件大小的差异。但它根本不是供应商所描述的。她说自己写的是没有编码的8位无符号二进制数据&#34;而不是Base64。
因此我们希望它失败但不一定会导致更大的有效载荷。请考虑接收String
格式的消息的WebSphere MQ将尝试转换它。如果消息的CCSID与GET
上请求的CCSID不同,则MQ将尝试转换。如果入站CCSID是UTF-16或任何双字节字符集,则某些字符将从一个字节扩展到两个字节 - 假设转换没有遇到导致其失败的无效二进制字符。
如果两个CCSID相同,那么在MQ类中不会尝试转换,但仍存在一个问题,即某些必须解析XML有效负载,根据定义,该有效负载无效,因此主题意外的结果。如果碰巧二进制有效负载不包含任何XML特殊字符并且解析器不会阻塞任何嵌入的空字节,则解析器将相当英雄的长度来原谅不符合的有效负载。如果它在没有阻塞的情况下到达</PdfBytes>
标记,则可能会认为有效负载是有效的,并在<PdfBytes>...</PdfBytes>
标记本身之间转换所有内容。大概是Base64。
当然,所有这些都是猜想。但是在有效负载明确不字符串数据的情况下,任何将其解析为字符串数据的尝试都将彻底失败或产生意外且可能奇怪的结果。你实际上不幸的是它并没有彻底失败,因为现在有一个期望,当问题显然是供应商的错误时,问题就在你的最后。
假设有效负载的内容保持不变,供应商应该发送bytes
消息,您应该以{{1}}接收它们。这至少可以解决MQ正在调整预期格式与实际接收格式的问题,但它仍然是无效的XML。如果供应商将消息集中的二进制数据发送到bytes
,并将其处理为String
,那么请计算您的祝福并以此方式使用它,但不要指望它是可靠的。最终,您将获得具有嵌入式XML特殊字符的有效负载,然后您将度过非常糟糕的一天。
理想情况下,供应商应该知道比在XML有效负载中发送二进制数据而不首先将其转换为字符串更好,并且由他们来修复它以使其符合XML规范并且可靠。
请参阅此MSDN页面:XML, SOAP, and Binary Data