postman - 使用 Postman 调用带有 multipart/form-data 的 Spring Boot 2 REST 服务会导致 EOFException
问题描述
在使用 Spring Boot 进行个人项目时,我必须开发一个接受文件和一些元数据的 Web 服务,我决定使用 Postman 客户端进行测试。
我正在使用的版本:
- Postman 版本:Postman for Mac 版本 7.8.0 OS X 18.7.0 / x64
- Java版本:1.8.0_212
- 春季启动版本:2.1.1.RELEASE
由于元数据可能非常结构化,我决定使用 multipart/form-data 内容类型,由两部分组成:
- 包含文件的“文件”部分
- 包含带有元数据的 json 的“body”部分
现在,Spring 引导配置。首先,我在 application.properties 中添加了以下几行:
## MULTIPART (MultipartProperties)
# Enable multipart uploads
spring.servlet.multipart.enabled=true
# Threshold after which files are written to disk.
spring.servlet.multipart.file-size-threshold=2KB
# Max file size.
spring.servlet.multipart.max-file-size=20MB
# Max Request Size
spring.servlet.multipart.max-request-size=25MB
然后我用端点创建了我的控制器
@PostMapping(Paths.Registrations.BASE)
@ResponseBody
public PostRegistrationResponseDto postRegistration(@RequestParam("file") MultipartFile file, @RequestParam("body") PostRegistrationRequestDto req) {
PostRegistrationResponseDto resp = new PostRegistrationResponseDto();
resp.setId(new Random().nextLong());
resp.setFileName(req.getFileName());
resp.setRegistrationTime(LocalDateTime.now());
return resp;
}
不幸的是,调用甚至没有到达 Spring:我收到一个 HTTP 500 错误与这个正文
<!doctype html>
<html lang="en">
<head>
<title>HTTP Status 500 – Internal Server Error</title>
<style type="text/css">
...
</style>
</head>
<body>
<h1>HTTP Status 500 – Internal Server Error</h1>
</body>
</html>
在我的服务器日志中,我没有收到任何异常,但是当我将调试器设置为阻止异常时,我看到 tomcat 使用此堆栈跟踪启动了一个 EOF 异常
java.io.EOFException
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1208)
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.read(NioEndpoint.java:1142)
at org.apache.coyote.http11.Http11InputBuffer.fill(Http11InputBuffer.java:729)
at org.apache.coyote.http11.Http11InputBuffer.parseRequestLine(Http11InputBuffer.java:352)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:294)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:791)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1417)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
我承认我什至不知道从哪里开始......有人可以给我一些提示我做错了什么吗?
谢谢 :)
解决方案
最后,我发现Tomcat抛出了很多异常,并不总是有意义的。
我遇到的问题与该异常无关,而是与 Spring 不会自动将 String 部分映射到 Dto 的事实有关。
为了使一切正常,我必须编写这个组件:
package it.aegidea.proofy.api.converters;
import com.fasterxml.jackson.databind.ObjectMapper;
import it.aegidea.proofy.api.dtos.proofyapi.PostRegistrationRequestDto;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.io.IOException;
@Component
public class PostRegistrationRequestDtoConverter implements Converter<String, PostRegistrationRequestDto> {
private final ObjectMapper objectMapper;
@Autowired
public PostRegistrationRequestDtoConverter(final ObjectMapper objectMapper) {
this.objectMapper = objectMapper;
}
@Override
public PostRegistrationRequestDto convert(String source) {
try {
return objectMapper.readValue(source, PostRegistrationRequestDto.class);
} catch (IOException e) {
return null;
}
}
}
通过这种方式,Spring 了解了如何将字符串映射到 PostRegistrationRequestDto 并且可以成功地将请求映射到端点上的类型。
推荐阅读
- ios - 如何在关闭时调用点击手势(iOS)
- powershell - 如何使用 PowerShell GUI 在用户 jpegPhoto 和 thumbnailPhoto 的属性中插入图片?
- django - Dhango 1.11 如何过滤一个过滤器的内容?
- javascript - 无法在打字稿中调用 svgdotjs rect 方法
- ios - 在 WhatsApp 上快速共享图像和文本
- php - 有时谷歌分析增强电子商务交易没有更新
- c# - 无法使用 C# Interop.Outlook 访问不同的收件人帐户文件夹
- excel - 如何使用重新格式化用户粘贴的文本块的长 For Next 循环来加速我的 VBA 代码?
- angular - 将 ngfor 与另一个 ngfor 中的动态可观察对象一起使用
- r - 如何在 R 中将 lib-paths 设置为具有单个目录,即“C:\Users\Username\Documents\...”