【问题标题】:Spring Boot upgrade to 2.2.5 causing required request part 'file' is not presentSpring Boot 升级到 2.2.5 导致所需的请求部分“文件”不存在
【发布时间】:2020-05-12 13:39:06
【问题描述】:
所以我们将 Spring Boot 从 2.0.3 升级到 2.2.5,这导致我们的文件导入开始失败。
所以我的代码是这样的:
public Result<FileResponse> importFile(@RequestParam(value = "file") MultipartFile file) {...}
我们有几个自定义过滤器,我们在嵌入式 Tomcat 9.0.3 上运行。我们收到类似于...required request part 'file' is not present... 的响应,带有堆栈跟踪。看起来文件没有正确填充。
【问题讨论】:
标签:
spring-boot
servlet-filters
【解决方案1】:
所以发生的事情是:
- Spring Boot 2.0.3 具有某些过滤器
- HiddenHttpProcessor 过滤器运行代码
request.getParts()。
- 因此运行它实际上会导致 Spring 执行魔术,其中 Spring 从输入流中读取,解析请求部分,填充请求部分,从流中删除请求部分,然后 Spring 就像从未读取过流一样。
- Spring Boot 升级到 2.2.5 导致过滤器运行的变化。因此,
request.getParts() 在我们的自定义过滤器运行之前从未运行过。
- 我们的自定义过滤器之一是包装请求。在创建打包请求期间,我们运行了
IOUtils.copy(this.request.getInputStream(),baos),它将我们的request.getInputStream() 复制到ByteArrayOutputStream。 这是为了绕过 Spring 的规则,即只允许调用一次 request.getInputStream()。
- 出于某种原因,将
request.getInputStream() 转换为任何类型的字节数组会将流更改为request.getParts() 无法正确解析它的程度。
- 因此您必须在操作
request.getInputStream() 之前调用request.getParts()。
这有点像 Spring InputStream 魔法和普通 servlet 过滤器模式之间的冲突。 Spring 对待他们内部的方式与外界如何称呼他们的代码不同。因为从技术上讲,request.getParts() 不应该被允许通过 Spring 自己的规则来操作流。