Spring Boot同一POST方法如何同时支持multipart/form-data和application/json
问题结论
你的使用场景是完全合理的,不少业务中都会存在同一个接口需要同时支持纯JSON请求和带文件的表单上传请求的需求。
报错原因
你遇到的报错是Spring MVC参数解析的逻辑导致的:
@RequestBody注解对应的消息转换器默认仅支持解析JSON、XML等非分片类型的请求体,不支持multipart/form-data类型- 当你在方法参数中同时声明
@RequestBody和@RequestPart时,Spring会先校验@RequestBody能否处理当前请求的Content-Type,遇到multipart/form-data类型时直接校验失败抛出异常,不会继续走到@RequestPart的解析逻辑,哪怕你把@RequestBody设为非必填也不生效
解决方案
方案一(最推荐):拆分为两个同路径的接口
Spring MVC支持同路径、不同consumes配置的接口自动按请求Content-Type路由,代码更清晰无兼容问题:
// 处理纯JSON请求 @PostMapping(path = "/multipart", consumes = MediaType.APPLICATION_JSON_VALUE) public String handleJsonRequest(@RequestBody InputJsonVO inputJsonVO) { // 你的业务逻辑 } // 处理带文件的multipart请求 @PostMapping(path = "/multipart", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) public String handleMultipartRequest(@RequestPart("file") MultipartFile file, @RequestPart("jsonString") InputJsonVO inputJsonVO) { // 你的业务逻辑 }
方案二:同一个方法内手动适配
如果确实需要把逻辑写在同一个方法内,可以移除参数中的@RequestBody,手动判断请求类型解析JSON:
@PostMapping(path = "/multipart", consumes = { MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_JSON_VALUE }) public String getMessage( HttpServletRequest request, @RequestPart(required = false, name = "file") MultipartFile file, @RequestPart(required = false, name = "jsonString") InputJsonVO multipartJson ) throws IOException { InputJsonVO inputJsonVO; String contentType = request.getContentType(); // 匹配JSON请求 if (contentType.startsWith(MediaType.APPLICATION_JSON_VALUE)) { ObjectMapper objectMapper = new ObjectMapper(); inputJsonVO = objectMapper.readValue(request.getInputStream(), InputJsonVO.class); } else { // 匹配multipart请求 inputJsonVO = multipartJson; // 可自行补充file、multipartJson的必填校验逻辑 } // 后续统一业务逻辑 }
注意:如果项目中有全局拦截器提前读取了请求输入流,需要自行封装请求实现流的重复读取,否则手动解析JSON时会读取不到内容
内容的提问来源于stack exchange,提问作者Sumanth_newbie
相关产品推荐
相关产品推荐

