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

如何使用Java的javax.mail.internet.MimeMultipart API处理多部分响应

使用javax.mail.internet.MimeMultipart处理多部分响应的完整实现

下面是基于你提供的代码框架,完善后的多部分响应处理逻辑,覆盖嵌套多部分、JSON、文件、普通文本等常见场景:

核心处理逻辑说明

遍历MimeMultipart的每个BodyPart,根据MIME类型做针对性处理:

  • 遇到嵌套的多部分类型(如multipart/mixed、multipart/alternative)时,递归调用处理方法
  • 解析application/json类型的内容为字符串并转为JSON对象
  • 处理各类文件类型,提取文件名并读取文件内容
  • 处理普通文本类型(如text/plain、text/html)

完整代码实现

import javax.mail.BodyPart;
import javax.mail.MessagingException;
import javax.mail.internet.MimeMultipart;
import javax.mail.util.ByteArrayDataSource;
import org.json.JSONObject;
import java.io.*;
import java.util.logging.Logger;

public class MultipartHandler {
    private static final Logger log = Logger.getLogger(MultipartHandler.class.getName());

    public void processMultipartResponse(InputStream in) throws MessagingException, IOException {
        ByteArrayDataSource dataSource = new ByteArrayDataSource(in, "multipart/form-data");
        MimeMultipart multipart = new MimeMultipart(dataSource);
        processMultipart(multipart);
    }

    private void processMultipart(Object content) throws MessagingException, IOException {
        if (!(content instanceof MimeMultipart)) {
            log.warn("不是有效的MimeMultipart类型,无法处理");
            return;
        }

        MimeMultipart multipart = (MimeMultipart) content;
        int count = multipart.getCount();
        log.debug("多部分内容总数: " + count);

        for (int i = 0; i < count; i++) {
            BodyPart bodyPart = multipart.getBodyPart(i);
            String contentType = bodyPart.getContentType();
            log.debug("当前BodyPart类型: " + contentType);

            if (bodyPart.isMimeType("multipart/*")) {
                // 递归处理所有嵌套的多部分类型
                log.info("发现嵌套多部分内容,开始递归处理: " + contentType);
                processMultipart(bodyPart.getContent());
            } else if (bodyPart.isMimeType("application/json")) {
                // 处理JSON类型内容
                String jsonContent = readBodyPartContent(bodyPart);
                log.info("JSON内容: " + jsonContent);
                // 转为JSON对象(这里用org.json示例,也可替换为Jackson/Gson)
                JSONObject jsonObject = new JSONObject(jsonContent);
                // 后续可根据业务需求处理JSON对象
                // 比如提取字段:String value = jsonObject.getString("key");
            } else if (bodyPart.isMimeType("text/*")) {
                // 处理普通文本类型(plain/html等)
                String textContent = readBodyPartContent(bodyPart);
                log.info("文本内容: " + textContent);
                // 业务逻辑处理文本
            } else if (bodyPart.isMimeType("application/octet-stream") || 
                       bodyPart.isMimeType("image/*") || 
                       bodyPart.isMimeType("text/csv")) {
                // 处理各类文件类型
                handleFileBodyPart(bodyPart);
            } else {
                log.warn("未处理的MIME类型: " + contentType);
                // 可选:读取未知类型内容做日志记录
                String unknownContent = readBodyPartContent(bodyPart);
                log.debug("未知类型内容: " + unknownContent);
            }
        }
    }

    /**
     * 读取BodyPart的内容为字符串
     */
    private String readBodyPartContent(BodyPart bodyPart) throws MessagingException, IOException {
        try (InputStream is = bodyPart.getInputStream();
             BufferedReader reader = new BufferedReader(new InputStreamReader(is))) {
            StringBuilder sb = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
            return sb.toString();
        }
    }

    /**
     * 处理文件类型的BodyPart
     */
    private void handleFileBodyPart(BodyPart bodyPart) throws MessagingException, IOException {
        // 获取文件名(从Content-Disposition头中提取)
        String disposition = bodyPart.getDisposition();
        String fileName = null;
        if (disposition != null && disposition.equalsIgnoreCase(BodyPart.ATTACHMENT)) {
            fileName = bodyPart.getFileName();
        }
        if (fileName == null) {
            fileName = "unknown-file-" + System.currentTimeMillis();
        }

        // 读取文件内容到字节数组
        byte[] fileBytes;
        try (InputStream is = bodyPart.getInputStream();
             ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
            byte[] buffer = new byte[1024];
            int bytesRead;
            while ((bytesRead = is.read(buffer)) != -1) {
                baos.write(buffer, 0, bytesRead);
            }
            fileBytes = baos.toByteArray();
        }

        log.info("处理文件: " + fileName + ",大小: " + fileBytes.length + "字节");
        // 业务逻辑:保存到文件系统、上传到存储服务等
        // 示例:保存到本地
        try (FileOutputStream fos = new FileOutputStream("/path/to/save/" + fileName)) {
            fos.write(fileBytes);
        }
    }
}

关键细节说明

  • 递归处理嵌套多部分:通过multipart/*匹配所有嵌套的多部分类型,避免遗漏不同子类型的嵌套结构
  • 通用内容读取方法:readBodyPartContent统一处理文本类内容的读取,简化代码
  • 文件处理:从Content-Disposition头提取文件名,读取字节数组后可灵活处理(保存本地、上传等)
  • 异常处理:代码中已包含基本的流关闭逻辑(try-with-resources),避免资源泄漏

内容的提问来源于stack exchange,提问作者Sharath K

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 01:25:26