【问题标题】:STAX API reading Binary dataSTAX API 读取二进制数据
【发布时间】:2012-12-08 05:43:36
【问题描述】:

我正在使用 STAX 事件 API 读取从 SOAP 调用接收到的二进制数据,并希望将其流式传输给消费者。来自 SOAP 调用的 XML 有效负载是这样的:

    .........
    <BinaryObject mimeCode="text/xml">PHNvYXAtZW52OkVudmVsb3BlIHhtbG5zOnNvYXAtZW52PSJodHRwOi8vc
         2NoZW1hcy54bWxzb2FwLhm9yZy9zb2FwL2VudmVsb3BlLyI+DQogICA8c29hcC1lbnY6SGVhZGVy
         Lz4NCiAgIDxzb2FwLWVudjpCb2R5Pg0KICAgICAgPG5tOkF0dGFjaG1lbnRGb2xkZXJEb2N1bWVudE
         ZpbGVDb250ZW50QnlJRFJlc3BvbnNlX3N5bmMgeG1sbnM6bm09Imh0dHA6Ly9zYXAuY29tL3hpL1NB
         UEdsb2JhbDIwL0dsb2JhbCIgeG1sbnM6cHJ4PSJ1cm46c2FwLmNvbTpwcm94eTpISlc6LzFTQUkvVE
         FTMEIzNDE4MTJBNTc5MDUyM0I5RTU6ODA0Ij4NCiAgICAgICAgIDxBdHRhY..... </BinaryObject>

以下是我用于解析数据并将数据发送给消费者的 java 代码

    XMLInputFactory inputFactory = XMLInputFactory.newInstance();
    inputFactory.setProperty(XMLInputFactory.IS_COALESCING, true);

    InputStream in;

    try {

        in = new ByteArrayInputStream(response.getBytes());

        XMLEventReader eventReader;
        eventReader = inputFactory.createXMLEventReader(in);

        while (eventReader.hasNext()) {
            XMLEvent event = eventReader.nextEvent();

            // Start element
            if (event.isStartElement()) {
                StartElement startElement = event.asStartElement();

                if (startElement.getName().getLocalPart().toString()
                        .equals("BinaryObject")) {

                    Iterator<Attribute> attributes = startElement
                            .getAttributes();

                    while (attributes.hasNext()) {
                        Attribute attribute = attributes.next();

                        if (attribute.getName().toString()
                                .equals("mimeCode")) {
                            mimeType = attribute.getValue();
                        }
                    }

                    event = eventReader.peek();

                    if (event.isCharacters()) {
                        event = eventReader.nextEvent();
                        content = event.asCharacters().getData();
                    }
                }
            }
        }

    } catch (XMLStreamException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    m_servletResponse.setContentType(mimeType);
        m_servletResponse.getWriter().print(javax.xml.bind.DatatypeConverter
                .printBase64Binary(content.getBytes()));

此代码存在多个问题:

  1. 对于较大的文件 (> 1 MB),我收到 StackOverflow 错误

  2. 即使是较小的文件,当我尝试使用 png 文件时,我也会收到文件无效的错误(在消费者处)。

我该如何克服这些问题?

PS:我是第一次使用 STAX !!

==================== 编辑: =====================**

根据下面 Evgeniy 的建议,我现在可以处理小文件(例如 PNG)。但是,对于大于 1 MB 的大型 PDF 文档,我会收到以下错误。关于这里出了什么问题的任何想法?

2012 12 09 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null#线程“http”中的异常-bio-8041-exec-9" | 2012 12 09 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null#java.lang.StackOverflowError| 2012 年 12 月 9 日 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null# 在 com.sun.org.apache .xerces.internal.impl.XMLScanner.isInvalid(XMLScanner.java:1334)| 2012 年 12 月 9 日 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null# 在 com.sun.org.apache .xerces.internal.impl.XMLScanner.scanCharReferenceValue(XMLScanner.java:1294)| 2012 年 12 月 9 日 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null# 在 com.sun.org.apache .xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3024)| 2012 年 12 月 9 日 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null# 在 com.sun.org.apache .xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2919)| 2012 年 12 月 9 日 06:50:19#+00#ERROR#System.err##anonymous#http-bio-8041-exec-9##seodportal#seodportal#web#null#null# 在 com.sun.org.apache .xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3059)|

【问题讨论】:

    标签: java binary-data stax


    【解决方案1】:

    首先,XMLEventReader 是为特殊用途而设计的,请改用XMLStreamReader。这是一个工作示例

            XMLInputFactory inputFactory = XMLInputFactory.newInstance();
            inputFactory.setProperty(XMLInputFactory.IS_COALESCING, true);
            InputStream in = new ByteArrayInputStream(response.getBytes());
            XMLStreamReader xr = inputFactory.createXMLStreamReader(in);
            while (xr.hasNext()) {
                int next = xr.next();
                if (next == XMLStreamConstants.START_ELEMENT) {
                    if (xr.getLocalName().equals("BinaryObject")) {
                        String mimeCode = xr.getAttributeValue(null, "mimeCode");
                        if (mimeCode.equals("text/xml")) {
                            xr.next();
                        // for efficiency we can access xr inner buffer chars directly
                        char[] b = xr.getTextCharacters();
                        int textStart = xr.getTextStart();
                        int textLength = xr.getTextLength();
                        // or simply get it as String  
                        String text = xr.getText();
                        // in this example I will use JDK's internal decoder com.sun.org.apache.xerces.internal.impl.dv.util.Base64                     
                        byte[] bytes = new Base64().decode(text);
    
                        }
                    }
                }
            }
    

    【讨论】:

    • 同样使用上述方法,这两个问题仍然存在,即当 BinaryObject 是 mime 类型 image/png 时,下载的图像无效(要进行 base64 编码?)。对于大于 1MB 的大文件,我仍然会遇到 StackOverflow 问题。
    • 将解码器添加到示例中,至于 SOE - 将堆栈跟踪添加到您的问题
    • 好。我建议不要使用JDK内部Base64,以apache commons-codec lib为例
    • 但是与大文件相关的问题仍然存在。请参阅我的原始帖子的编辑。
    • 如果我将 IS_COALESCING 设置为 FALSE,错误就会消失。但是,文件在下载时已损坏。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    • 2013-10-17
    • 2021-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    相关资源
    最近更新 更多