2012-12-08 100 views
1

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

......... 
    <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)。然而对于大型的PDF文档> 1 MB,我得到下面的错误。任何关于这里发生了什么问题的想法?

2012 12 09 06:50:19#+ 00#错误#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#错误#System.err ## anonymous#http-bio-8041-exec-9 ## seodportal#seodportal#web#null#null#java.lang.StackOverflowError | 2012 12 09 06:50:19#+ 00#错误#System.err ## anonymous#http-bio-8041-exec-9 ## seodportal#seodportal#web#null#null#at com.sun.org。 apache.xerces.internal.impl.XMLScanner.isInvalid(XMLScanner.java:1334)| 2012 12 09 06:50:19#+ 00#错误#System.err ## anonymous#http-bio-8041-exec-9 ## seodportal#seodportal#web#null#null#at com.sun.org。 apache.xerces.internal.impl.XMLScanner.scanCharReferenceValue(XMLScanner.java:1294)| 2012 12 09 06:50:19#+ 00#错误#System.err ## anonymous#http-bio-8041-exec-9 ## seodportal#seodportal#web#null#null#at com.sun.org。 apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl $ FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3024)| 2012 12 09 06:50:19#+ 00#错误#System.err ## anonymous#http-bio-8041-exec-9 ## seodportal#seodportal#web#null#null#at com.sun.org。 apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl $ FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:2919)| 2012 12 09 06:50:19#+ 00#错误#System.err ## anonymous#http-bio-8041-exec-9 ## seodportal#seodportal#web#null#null#at com.sun.org。 apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl $ FragmentContentDriver.next(XMLDocumentFragmentScannerImpl.java:3059)|

回答

1

首先,XMLStreamReader是专为特殊目的而设计的,请改用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); 

        } 
       } 
      } 
     } 
+0

同样采用上述方法,当BinaryObject是MIME类型image/png,下载的图像无效(base64编码完成?)时,这两个问题仍然存在。对于大于1MB的文件,我仍然遇到StackOverflow问题。 – mithrandir

+0

添加解码器为例,对于SOE - 添加堆栈跟踪给你问题 –

+0

谢谢你的帮助。 – mithrandir