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

Java中@MultipartForm发送多部件表单参数报400错误排查

问题分析与解决方案

问题描述

在Java中使用Resteasy客户端通过@MultipartForm发送多部件文件及表单参数到Spring服务器时,收到400 Bad Request错误,服务器抛出org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present。

服务器端接口

@RequestMapping(value = "doSomething", method = RequestMethod.POST,
        headers = {"content-type=multipart/mixed","content-type=multipart/form-data"}, produces = MediaType.TEXT_PLAIN_VALUE)
ResponseEntity<String> doSomething(
        @RequestPart("name") String name,
        @RequestPart("file") MultipartFile file,
        @RequestPart("type") String type
);

客户端接口

@POST
@Path("doSomething")
@Produces(MediaType.TEXT_PLAIN)
@Consumes(MediaType.MULTIPART_FORM_DATA)
String doSomething(@MultipartForm MultipartBody body);

客户端MultipartBody类

public class MultipartBody {

    @FormParam("name")
    @PartType(MediaType.TEXT_PLAIN)
    public String name;

    @FormParam("file")
    @PartType(MediaType.APPLICATION_OCTET_STREAM)
    public InputStream file;

    @FormParam("type")
    @PartType(MediaType.TEXT_PLAIN)
    public String type;
}

客户端请求体内容

Body: --02d16fb7-e89e-4847-adaa-d64db0c86700
Content-Disposition: form-data; name="file"
Content-Type: application/octet-stream

testerito
--02d16fb7-e89e-4847-adaa-d64db0c86700
Content-Disposition: form-data; name="name"
Content-Type: text/plain

test
--02d16fb7-e89e-4847-adaa-d64db0c86700
Content-Disposition: form-data; name="type"
Content-Type: text/plain

test
--02d16fb7-e89e-4847-adaa-d64db0c86700-- 

问题原因

  1. 服务器端headers配置错误:
    当前headers = {"content-type=multipart/mixed","content-type=multipart/form-data"}要求请求同时满足这两个Content-Type条件,这是不可能的,导致请求无法正确匹配接口,或Spring解析时出现异常。
  2. 客户端file请求部分缺少filename属性:
    Spring的@RequestPart("file") MultipartFile要求对应的请求部分在Content-Disposition头中包含filename参数,否则Spring无法将其识别为文件类型的请求部分,从而抛出缺失file部件的异常。

解决方案

1. 修复服务器端接口配置

将headers替换为consumes属性,正确指定支持的多部件类型:

@RequestMapping(value = "doSomething", method = RequestMethod.POST,
        consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.MULTIPART_MIXED_VALUE},
        produces = MediaType.TEXT_PLAIN_VALUE)
ResponseEntity<String> doSomething(
        @RequestPart("name") String name,
        @RequestPart("file") MultipartFile file,
        @RequestPart("type") String type
);

如果仅需支持multipart/form-data,可简化为consumes = MediaType.MULTIPART_FORM_DATA_VALUE。

2. 修复客户端请求,让file部分携带filename

以下三种方式任选其一:

方式一:修改MultipartBody,手动添加Content-Disposition头

public class MultipartBody {

    @FormParam("name")
    @PartType(MediaType.TEXT_PLAIN)
    public String name;

    // 为file部件添加包含filename的Content-Disposition头
    @HeaderParam("Content-Disposition")
    @FormParam("file")
    public String fileDisposition = "form-data; name=\"file\"; filename=\"your-file-name.txt\"";

    @FormParam("file")
    @PartType(MediaType.APPLICATION_OCTET_STREAM)
    public InputStream file;

    @FormParam("type")
    @PartType(MediaType.TEXT_PLAIN)
    public String type;
}

方式二:将InputStream替换为File类型(Resteasy自动处理filename)

public class MultipartBody {

    @FormParam("name")
    @PartType(MediaType.TEXT_PLAIN)
    public String name;

    @FormParam("file")
    @PartType(MediaType.APPLICATION_OCTET_STREAM)
    public File file; // 使用File类型时,Resteasy会自动添加filename参数

    @FormParam("type")
    @PartType(MediaType.TEXT_PLAIN)
    public String type;
}

方式三:使用MultipartFormDataOutput手动构建请求(更灵活)

直接构建多部件请求体,无需实体类:

MultipartFormDataOutput output = new MultipartFormDataOutput();
output.addFormData("name", "test", MediaType.TEXT_PLAIN_TYPE);
output.addFormData("type", "test", MediaType.TEXT_PLAIN_TYPE);
// 添加文件时指定filename
output.addFormData("file", new FileInputStream("/path/to/your/file"), MediaType.APPLICATION_OCTET_STREAM_TYPE, "test.txt");

// 发送请求
Response response = resteasyClient.target("your-api-url")
        .request(MediaType.TEXT_PLAIN)
        .post(Entity.entity(output, MediaType.MULTIPART_FORM_DATA));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 08:40:34