如何在额外Servlet Filter中解析multipart请求且不丢失上传内容
实现方案
问题梳理
- 自定义Filter需要对
multipart类型POST请求做前置校验,在请求抵达无修改权限的Jersey业务端点前,就要拦截拒绝不符合要求的请求。 - 配置常规multipart解析参数后,可以解决报错:
Unable to process parts as no multi-part configuration has been provided - 基础配置完成后,无论是自定义
CommonsMultipartResolver还是系统内置解析器,运行时都不会再抛出上述错误,但会出现请求被解析后上传内容丢失的问题。 - 现有参考方案需要自定义
CommonsMultipartResolver处理内容丢失问题,实现较重,目标是仅新增Filter就满足需求,不需要做请求复制。
最简实现(无需复制请求/包装请求)
利用Servlet 3.0+规范自带的multipart解析缓存机制即可实现,不需要额外引入Commons FileUpload组件,也不需要自定义MultipartResolver。
- 首先完成multipart基础配置,Spring Boot环境可直接在配置文件添加:
spring: servlet: multipart: enabled: true # 根据业务需求调整大小限制 max-file-size: 100MB max-request-size: 100MB
如果是非Spring Boot环境,需要给Servlet配置添加MultipartConfigElement,确保容器开启multipart解析能力。
- 编写自定义校验Filter,逻辑按如下顺序实现:
- 首先判断请求
Content-Type是否为multipart/form-data,非该类型请求直接放行 - 针对multipart请求,直接调用标准Servlet接口
request.getParts()获取所有请求分片,遍历分片的过程中完成自定义校验(比如文件后缀、大小、表单字段合法性等),校验不通过直接返回对应错误响应 - 校验通过后直接放行请求即可,不需要做任何请求包装、流复制操作
- 首先判断请求
关键注意点:整个Filter逻辑中不要手动调用
request.getInputStream()或request.getReader()读取请求体,所有和multipart相关的操作都走getParts()/getPart(name)标准接口。容器解析完Part后会自动缓存解析结果,后续Jersey端点读取请求时会直接复用缓存内容,不会出现流被提前消费导致的上传内容丢失问题。
避坑说明
- 不要在Filter中手动解析请求输入流:一旦手动把输入流读尽又没做完整缓存,后续链路必然拿不到上传内容。
- 不需要额外自定义CommonsMultipartResolver:Servlet容器自带的解析能力已经支持结果复用,完全满足前置校验场景的需求,实现比自定义解析器简洁很多。
内容的提问来源于stack exchange,提问作者rob2universe
相关产品推荐
相关产品推荐

