You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用@FormDataParam注解导致multipart/form-data请求返回400 Bad Request(Jersey 3.1.10、Java 17、Tomcat 10)

使用@FormDataParam注解导致multipart/form-data请求返回400 Bad Request(Jersey 3.1.10、Java 17、Tomcat 10)

嘿,作为资深API开发者碰到这种新端点的400问题确实闹心,我来帮你捋捋Jersey 3.x环境下最常见的几个坑!

优先级最高的排查点:没配置Multipart支持

Jersey 3.x之后,multipart/form-data的处理不再是默认内置的了,这是绝大多数人踩的第一个坑:

  1. 添加依赖包
    如果用Maven,在pom.xml里补上:
    <dependency>
        <groupId>org.glassfish.jersey.media</groupId>
        <artifactId>jersey-media-multipart</artifactId>
        <version>3.1.10</version>
    </dependency>
    
    Gradle的话就加:
    implementation 'org.glassfish.jersey.media:jersey-media-multipart:3.1.10'
    
  2. 注册MultipartFeature
    要么在你的Application配置类里注册:
    @ApplicationPath("/")
    public class MyApiConfig extends ResourceConfig {
        public MyApiConfig() {
            packages("com.your.resource.package"); // 替换成你的接口所在包
            register(org.glassfish.jersey.media.multipart.MultipartFeature.class);
        }
    }
    
    用web.xml配置的话,就给Jersey Servlet加初始化参数:
    <servlet>
        <servlet-name>JerseyServlet</servlet-name>
        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
        <init-param>
            <param-name>jersey.config.server.provider.classnames</param-name>
            <param-value>org.glassfish.jersey.media.multipart.MultipartFeature</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>
    

其次检查请求参数的匹配度

  • 确认前端/测试工具(比如Postman)里的form-data参数名,和@FormDataParam("file")里的"file"完全一致——大小写是敏感的!比如前端传的是"File"或者"upload_file",Jersey会找不到参数直接返回400。
  • 确保请求里确实携带了这个file参数,空请求或者漏传参数也会触发400。

然后验证请求的Content-Type

一定要确保请求头的Content-Typemultipart/form-data; boundary=xxxxxx(xxxxxx是自动生成的边界字符串)。有些工具可能误设成application/x-www-form-urlencoded,或者没带boundary,这会让Jersey无法解析请求体,直接报错。

别忘排查Tomcat的上传大小限制

Tomcat 10默认对上传文件的大小有限制,如果测试文件过大也会返回400:

  1. 修改Tomcat的conf/web.xml,添加文件上传过滤器:
    <filter>
        <filter-name>fileUploadFilter</filter-name>
        <filter-class>org.apache.tomcat.util.http.fileupload.servlet.FileUploadFilter</filter-class>
        <init-param>
            <param-name>maxFileSize</param-name>
            <param-value>104857600</param-value> <!-- 100MB,按需调整 -->
        </init-param>
        <init-param>
            <param-name>maxRequestSize</param-name>
            <param-value>104857600</param-value>
        </init-param>
    </filter>
    <filter-mapping>
        <filter-name>fileUploadFilter</filter-name>
        <url-pattern>/v1/upload</url-pattern>
    </filter-mapping>
    
  2. 或者修改conf/server.xml里的Connector,把maxPostSize设为-1表示不限制:
    <Connector port="8080" protocol="HTTP/1.1"
               connectionTimeout="20000"
               maxPostSize="-1"
               redirectPort="8443"/>
    

可选优化:完善方法参数

可以把FormDataContentDisposition也注入进来,既能拿到文件名等信息,还能避免一些注入异常:

@POST
@Path("/v1/upload")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response upload(
        @FormDataParam("file") InputStream file,
        @FormDataParam("file") FormDataContentDisposition fileDisposition
) {
    String fileName = fileDisposition.getFileName();
    // 这里写文件处理逻辑,比如保存到磁盘
    return Response.ok("Received file: " + fileName).build();
}

先从Multipart的依赖和注册开始排查,这是90%以上的人碰到这个问题的根源!如果还不行,再依次检查参数名、请求头和Tomcat限制。

备注:内容来源于stack exchange,提问作者Brien Halstead

火山引擎 最新活动