Spring 引导升级到 2.2.5 导致所需的请求部分 'file' 不存在
Spring Boot upgrade to 2.2.5 causing required request part 'file' is not present
因此我们将 Spring 引导从 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 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 自己的规则来操纵流。
因此我们将 Spring 引导从 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 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 自己的规则来操纵流。