首页 > 解决方案 > XML 与 Base64 编码字符串到 PDF

问题描述

我有一个 XML,其中我将 PDF 文档作为 Base64 编码字符串。

<?xml version="1.0" encoding="UTF-8"?>
<ns0:Messages xmlns:ns0="http://sap.com/xi/XI/SplitAndMerge">
   <ns0:Message1>
      <ns1:Record xmlns:ns1="urn:test.com:pdf">
         <Field>**Contains the base 64 encoded string of the actual PDF**</Field>
      </ns1:Record>
   </ns0:Message1>
</ns0:Messages>

我尝试在下面执行转换。我尝试将 XML 内容作为输入并执行 Base 64 转换。

public void transform(TransformationInput transformationInput, TransformationOutput transformationOutput) throws StreamTransformationException {
        try {
            InputStream inputstream = transformationInput.getInputPayload().getInputStream();
            OutputStream outputstream = transformationOutput.getOutputPayload().getOutputStream();
            // Copy Input content to Output content
            byte[] b = new byte[inputstream.available()];
            inputstream.read(b);

                    Base64.Decoder dec = Base64.getDecoder();
                byte[] decbytes = dec.decode(b);

           outputstream.write(decbytes);
        } catch (Exception e) {
        }
    }

我使用的工具不需要 main 并且代码在运行时执行。但它不起作用。我还尝试删除 XML 标签。而且我还在工具的导入部分单独导入了 java.util.Base64。任何帮助将不胜感激。

标签: javaxmljava-8base64decode

解决方案


InputStream.available() 的文档中

使用此方法的返回值来分配旨在保存此流中所有数据的缓冲区是不正确的。

从 InputStream 读取时必须使用循环。并且在调用 InputStream.read 时使用返回值至关重要,因为不能保证您的字节数组会被填充。

您还需要记住关闭您的流。如果不这样做,则会造成内存泄漏,并且某些数据可能不会写入 OutputStream。

Base64.Decoder 有一个有用的方法wrap(InputStream),它可以让您将解码视为普通的 InputStream。

最后:永远不要写一个空catch块。如果您不确定如何处理异常,请不要——删除 try/catch,添加throws IOException到您的方法的签名中,并让更高级别的应用程序决定最佳操作过程(例如向最终用户显示一条错误消息)。

所以,你会想要这样的东西:

public void transform(TransformationInput transformationInput,
                      TransformationOutput transformationOutput)
throws StreamTransformationException,
       IOException {

    try (InputStream inputstream = Base64.getDecoder().wrap(
            transformationInput.getInputPayload().getInputStream());
        OutputStream outputstream =
            transformationOutput.getOutputPayload().getOutputStream()) {

        // Copy Input content to Output content
        byte[] b = new byte[inputstream.available()];
        int bytesRead;
        while ((bytesRead = inputstream.read(b)) >= 0) {
            outputstream.write(b, 0, bytesRead);
        }
    }
}

从 Java 9 开始,您可以使用InputStream.transferTo完全放弃字节数组:

public void transform(TransformationInput transformationInput,
                      TransformationOutput transformationOutput)
throws StreamTransformationException,
       IOException {

    try (InputStream inputstream = Base64.getDecoder().wrap(
            transformationInput.getInputPayload().getInputStream());
        OutputStream outputstream =
            transformationOutput.getOutputPayload().getOutputStream()) {

        inputstream.transferTo(outputstream);
    }
}

请注意:我不确定 TransformationInput 和 TransformationOutput 类是什么,但如果 TransformationOutput 表示 XML 文件,二进制数据将不兼容,因为某些字节值不允许直接出现在 XML 文档中。这就是 XML 将嵌入的二进制数据表示为十六进制或 base 64 的原因。


推荐阅读