You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java中处理SOAP API返回的application/octet-stream格式PDF附件的问题

Java中处理SOAP API返回的application/octet-stream格式PDF附件的问题

看起来你踩了一个很常见的坑——把二进制的PDF数据当成普通字符串来处理,这直接破坏了原始的字节信息,导致生成的Base64还原不出正确的PDF。我来给你梳理下问题所在,以及正确的处理方式:

问题根源

你当前的代码把整个响应流用BufferedReader以UTF-8编码读取成字符串,这对二进制数据(比如PDF)是致命的:

  • UTF-8是字符编码,专门用于处理文本数据,非字符的二进制字节(比如PDF里的压缩流)会被UTF-8解析器转换成替换字符�,完全丢失原始字节信息。
  • 之后你从这个损坏的字符串里截取PDF内容,再转Base64,自然无法还原出正确的PDF文件。

正确的处理思路

SOAP API返回的是MIME多部分(multipart)响应,包含XML主体和二进制PDF附件两部分。处理这种响应的正确方式是:

  1. 直接操作原始的InputStream,不要转成字符串。
  2. 使用成熟的MIME解析库(比如JavaMail的MimeMultipart)来拆分响应中的各个部分。
  3. 定位到application/octet-stream类型的附件部分,读取其原始二进制字节,再转Base64或直接保存文件。

具体代码修改

1. 依赖准备(Maven)

首先需要引入JavaMail库来解析MIME多部分内容:

<dependency>
    <groupId>javax.mail</groupId>
    <artifactId>javax.mail-api</artifactId>
    <version>1.6.2</version>
</dependency>
<dependency>
    <groupId>com.sun.mail</groupId>
    <artifactId>javax.mail</artifactId>
    <version>1.6.2</version>
</dependency>

2. 替换响应处理逻辑

把你代码中从// Get response from the server开始的部分,替换成以下代码:

// 获取响应的Content-Type头(包含MIME边界信息,必须用来解析多部分内容)
String contentType = connection.getHeaderField("Content-Type");
// 直接获取原始响应流,不要转成字符串
InputStream responseStream = responseCode >= 200 && responseCode < 300 
    ? connection.getInputStream() 
    : connection.getErrorStream();

String base64EncodedAttachment = null;

try {
    // 用JavaMail解析MIME多部分响应
    ByteArrayDataSource dataSource = new ByteArrayDataSource(responseStream, contentType);
    MimeMultipart mimeMultipart = new MimeMultipart(dataSource);

    // 遍历所有MIME部分,找到PDF附件
    for (int i = 0; i < mimeMultipart.getCount(); i++) {
        BodyPart bodyPart = mimeMultipart.getBodyPart(i);
        String partContentType = bodyPart.getContentType();
        String partContentId = bodyPart.getContentID();

        // 可以通过Content-Type或Content-ID定位附件(根据你的响应,Content-ID是http://tempuri.org/1/638744554073071663)
        boolean isPdfAttachment = partContentType.contains("application/octet-stream") 
            || (partContentId != null && partContentId.contains("1/638744554073071663"));

        if (isPdfAttachment) {
            // 读取原始二进制PDF数据
            InputStream pdfStream = bodyPart.getInputStream();
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = pdfStream.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesRead);
            }
            byte[] pdfBytes = baos.toByteArray();

            // 直接将原始二进制转Base64
            base64EncodedAttachment = Base64.getEncoder().encodeToString(pdfBytes);
            logger.info("成功提取并编码PDF附件");
            break;
        }
    }
} catch (MessagingException | IOException e) {
    logger.error("解析MIME响应失败", e);
} finally {
    if (responseStream != null) {
        responseStream.close();
    }
}

3. 移除错误的字符串处理代码

删除你原来的getpdfDataEncoded方法,因为它的处理逻辑从根源上就是错误的,不需要再使用。

额外提示

  • 如果你不想引入JavaMail依赖,也可以手动解析MIME多部分响应,但需要自己处理边界拆分、头部解析等逻辑,非常容易出错,不推荐。
  • 永远记住:二进制数据(图片、PDF、压缩包等)必须直接用InputStream/OutputStream处理,绝对不能转成String再操作,否则必然损坏数据。

备注:内容来源于stack exchange,提问作者Sourav Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 07:14:50