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

使用Apache HttpClient5 Fluent:如何还原存储的MultipartEntity参数?

解决方法

一、直接从MultipartEntity获取参数(无需转byte[]后再解析)

如果还未将MultipartEntity转为byte[],可以直接从MultipartFormEntity(MultipartEntityBuilder.build()的返回类型)中提取参数,这是最直接高效的方式:

// 校验并转换类型
if (httpEntity instanceof MultipartFormEntity multipartFormEntity) {
    // 获取所有表单部件
    List<FormPart> parts = multipartFormEntity.getParts();
    for (FormPart part : parts) {
        String paramName = part.getName();
        ContentType contentType = part.getContentType();

        // 处理文本参数
        if (ContentType.TEXT_PLAIN.isCompatible(contentType)) {
            String textValue = EntityUtils.toString(part.getBody(), StandardCharsets.UTF_8);
            System.out.printf("文本参数:%s = %s%n", paramName, textValue);
        }
        // 处理文件参数
        else if (contentType.getMimeType().startsWith("image/") || ContentType.APPLICATION_OCTET_STREAM.isCompatible(contentType)) {
            String fileName = part.getFilename();
            System.out.printf("文件参数:%s,文件名:%s%n", paramName, fileName);
            // 如需读取文件内容,可调用EntityUtils.toByteArray(part.getBody())
        }
    }
}

二、从存储的byte[]解析回Multipart参数

如果已经将byte[]存入数据库,需要先提前保存Multipart的boundary分隔符(生成MultipartEntity时获取),再用MultipartStream解析:

步骤1:生成MultipartEntity时保存boundary

HttpEntity httpEntity = MultipartEntityBuilder.create()
        .addTextBody("name", "张三", ContentType.TEXT_PLAIN.withCharset(StandardCharsets.UTF_8))
        .addBinaryBody("file", new File("C:\\Users\\123\\Desktop\\QQ截图20231010143306.png"))
        .build();

// 获取并保存boundary(和byte[]一起存入数据库)
String boundary = ((MultipartFormEntity) httpEntity).getBoundary();

步骤2:从数据库取出byte[]和boundary后解析

// 从数据库取出的字节数组和boundary
byte[] multipartByteArray = /* 从数据库获取 */;
String boundary = /* 从数据库获取 */;

ByteArrayInputStream inputStream = new ByteArrayInputStream(multipartByteArray);
MultipartStream multipartStream = new MultipartStream(inputStream, boundary.getBytes(StandardCharsets.UTF_8), null, StandardCharsets.UTF_8);

LinkedMultiValueMap<String, Part> partMap = new LinkedMultiValueMap<>();
boolean hasNextPart = multipartStream.skipPreamble();

while (hasNextPart) {
    // 解析部件头部信息
    Header[] headers = multipartStream.readHeaders();
    String paramName = null;
    String fileName = null;
    ContentType contentType = null;

    for (Header header : headers) {
        if ("Content-Disposition".equalsIgnoreCase(header.getName())) {
            String headerValue = header.getValue();
            // 匹配参数名
            Matcher nameMatcher = Pattern.compile("name=\"([^\"]+)\"").matcher(headerValue);
            if (nameMatcher.find()) paramName = nameMatcher.group(1);
            // 匹配文件名
            Matcher fileNameMatcher = Pattern.compile("filename=\"([^\"]+)\"").matcher(headerValue);
            if (fileNameMatcher.find()) fileName = fileNameMatcher.group(1);
        } else if ("Content-Type".equalsIgnoreCase(header.getName())) {
            contentType = ContentType.parse(header.getValue());
        }
    }

    if (paramName != null) {
        // 读取部件内容
        ByteArrayOutputStream partOut = new ByteArrayOutputStream();
        multipartStream.readBodyData(partOut);
        byte[] partContent = partOut.toByteArray();

        // 封装为自定义Part对象(可根据需求调整)
        Part part = new Part() {
            @Override public String getName() { return paramName; }
            public String getFilename() { return fileName; }
            public ContentType getContentType() { return contentType; }
            public byte[] getContent() { return partContent; }
        };

        partMap.add(paramName, part);
    }

    hasNextPart = multipartStream.readBoundary();
}

// 解析完成后,partMap即为参数映射

关键注意事项

  • 存储byte[]时必须同步保存boundary,否则无法正确解析Multipart内容。
  • 大文件建议只记录文件名、参数名、文件大小等元信息,避免数据库体积过载。
  • 使用EntityUtils处理流时,建议用try-with-resources确保资源释放。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 23:09:55