繁体   English   中英

从XML元素内容获取InputStream

[英]Obtain InputStream from XML element content

我的servlet的doPost()接收到一个HttpServletRequest,它的ServletInputStream向我发送了一大堆用XML包装的uuencoded数据。 例如,有一个元素:

<filedata encoding="base64">largeChunkEncodedHere</filedata>

我需要解码该块并将其写入文件。 我想从块中获取InputStream,使用MimeUtility将其解码为流,然后使用该流来写入文件-我不希望不将这个大块读取到内存中。

XML是扁平的; 即没有太多的嵌套。 我的第一个想法是使用SAX解析器,但我不知道如何执行流传递以仅读取块。

感谢您的想法。

格伦

编辑1:这篇文章中注意JB Nizet的悲观答案。

编辑2:我在下面肯定地回答了我自己的问题,并在下面将maximdim的回答标记为正确,即使它并不能完全回答问题,也确实将我引向了StAX API和Woodstox。

Woodstox的另一个建议:它也可以从内部高效解码base64编码的内容。 为此,您需要将XMLStreamReader转换为XMLStreamReader2 (或TypedXMLStreamReader ),这是Stax2扩展API的一部分。

但是,您将获得方法readElementAsBinary()getElementAsBinary() ,它们可以自动处理Base64解码。 XMLStreamWriter2同样具有用于写入二进制数据的Base64编码方法。

您可以使用SAX筛选器或XPath仅获取您感兴趣的元素。一旦有了元素的内容,就将其传递给MimeUtility.decode()并将流写入文件。

我建议您使用代码示例更新您的问题,并让我们知道哪些无效。

更新:

这是使用StaX2解析器(Woodstox)的示例代码。 出于某种原因,至少乍一看,JDK中包含的StaX解析器似乎没有可比较的getText()方法。

显然,输入(r)和输出(w)可以是任何Reader / Writer或Stream-以String为例。

    Reader r = new StringReader("<foo><filedata encoding=\"base64\">largeChunkEncodedHere</filedata></foo>");
    Writer w = new StringWriter();

    XMLInputFactory2 xmlif = (XMLInputFactory2)XMLInputFactory2.newInstance();
    XMLStreamReader2 sr = (XMLStreamReader2)xmlif.createXMLStreamReader(r);

    boolean flag = false;
    while (sr.hasNext()) {
        sr.next();
        if (sr.getEventType() == XMLStreamConstants.START_ELEMENT) {
            if ("filedata".equals(sr.getLocalName())) {
                flag = true;
            }
        }
        else if (sr.getEventType() == XMLStreamConstants.CHARACTERS) {
            if (flag) {
                sr.getText(w, false);
                break;
            }
        }
    }
    System.out.println(w);

以下是有关使用Woodstox框架在使用StAX进行解析时如何从元素进行流传输的一些详细信息。

有一个很好的概述这篇文章

在XMLInputFactory中,我们可以使用ServletInputStream调用createXMLStreamReader(java.io.InputStream流)。 这将返回一个XMLStreamReader2,它具有一个getText(Writer w,boolean prepareContents)方法,该方法为写入的字节数返回一个int。 此方法必须实现。 在实现Stax2ReaderImpl中有此实现

// // // StAX2, Pass-through text accessors
public int getText(Writer w, boolean preserveContents)
    throws IOException, XMLStreamException
{
    char[] cbuf = getTextCharacters();
    int start = getTextStart();
    int len = getTextLength();

    if (len > 0) {
        w.write(cbuf, start, len);
    }
    return len;
}

在此代码中,我们将需要更改getTextCharacters()方法,以使其从InputStream中读取。 在Woodstox测试TestGetSegmentedText testSegmentedGetCharacters()方法中,我们看到使用了sr.getTextCharacters(offset,buf,start,len)方法。 实际上,多参数XMLStreamReader.getTextCharacters()的javadoc显示了以下实现。

int length = 1024;
char[] myBuffer = new char[ length ];
for ( int sourceStart = 0 ; ; sourceStart += length ) {
    int nCopied = stream.getTextCharacters( sourceStart, myBuffer, 0, length );
    if (nCopied < length) {
        break;
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM