springboot2.7文件上传报错,获取到的文件为空

新项目准备使用最新的springboot(2.7.2),但是发现文件上传报错,后台获取到的文件为空。问题排查过程记录下。
如果需要看原因,可直接跳转原因

1. 问题表现

获取到的文件为空
获取到的文件为空
同时控制台报错json解析失败

在这里插入图片描述

2.问题分析

2.1 第一次问题分析

  1. 看到控制台报json解析失败。报错位置位于xsswrapper中,作用为重复读取post请求body数据,并进行非法字符过滤。
    因为文件上传content-type为multipart/form-data,所以此处添加不是application/json时,直接返回。发现不起作用
    添加不是application/json时,直接返回
  2. 看到request类型为StandardMultipartHttpServletRequest,手动搜索了一下该类,断点parseRequest,发现request.getParts()获取到的为0。对比springboot旧版本项目,发现此处有问题。
    在这里插入图片描述
    所以,在显示时xsswrapper处理body数据之前,手动调用一下,看下返回什么(因为xsswrapper中报错了)
    在这里插入图片描述
    手动调用一下后发现,此处可以正确获取到文件parts,同时后面setRequestBody(从流中读取body数据)正常,不会读取到文件信息。
    至此,能够解决问题,但是不知道什么原因。

2.2 第二次问题分析

后来,刚好有点空闲时间,准备找下什么原因。
花了好长一段时间追踪Tomcat源码,看下request流转过程是怎样的,为什么会从流中读取到文件信息(结果没找到…)。

看到一篇博文,Tomcat如何处理文件上传的,其中提到Request类中有个parseParameters处理参数,里面有处理multipart/form-data

断点发现,旧版本中会调用该方法,而新版本(2.7.2)却不会。通过查看旧版本中调用该方法时的调用栈,发现最终是在HiddenHttpMethodFilter中
在这里插入图片描述

HiddenHttpMethodFilter中会调用request.getParameter()在这里插入图片描述
对比新版本和旧版本filter信息,发现两者filter数量存在差异
新版本:
在这里插入图片描述
旧版本:
在这里插入图片描述
至此,问题原因浮出水面,因为新版本中没有HiddenHttpMethodFilter。

通过旧版本中点击HiddenHttpMethodFilter中usages(不得不说,idea功能真的强大)
在这里插入图片描述
发现是在WebMvcAutoConfiguration中注册的,对比新旧版本发现了问题所在
左侧为新版本(2.7.2),右侧为旧版本(2.0.9.RELEASE)
在这里插入图片描述
旧版本中默认注册HiddenHttpMethodFilter,而新版本中默认不注册,需要手动注册spring.mvc.hiddenmethod.filter.enabled=true
添加该配置后,文件上传正常。
至此问题解决,如果不需要该filter,可以手动调用一下request.getParameterMap(),初始化参数处理

3.原因

新版本中没有自动注册HiddenHttpMethodFilter,导致没有调用request.parseParameters(对参数进行处理,包括multipart/form-data)
左侧为新版本(2.7.2),右侧为旧版本(2.0.9.RELEASE)
在这里插入图片描述

4.解决

需要org.apache.catalina.connector.Request.parseParameters()执行到

  1. 通过添加spring.mvc.hiddenmethod.filter.enabled=true配置
  2. 或者手动调用下request.getParameterMap(),初始化参数处理
Map<String, String[]> parameterMap = request.getParameterMap();

5.涉及版本

springbootv2.2.0.M5及之后
看了下WebMvcAutoConfiguration记录,发现从v2.1.0.M2开始添加了@ConditionalOnProperty注解,matchIfMissing=true。
v2.2.0.M5之后,matchIfMissing变为false

在这里插入图片描述
在这里插入图片描述

  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值