问题复现
在使用SpringBoot3.2.0版本中使用文件上传一直出现错误:MissingServletRequestPartException: Required request part ‘file’ is not present,检查了接口配置和postman请求都没问题。最后发现是自己的请求封装器有问题
这是我的接口定义还有postman请求截图
@PostMapping("/upload")
@Operation(summary = "上传文件", description = "uploadFile")
public Object upload(@RequestPart(name = "file") MultipartFile multipartFile) {
return qnyFileService.directUpload(multipartFile);
}
原因分析
传统的json请求使用的是HttpServletRequest,但是文件上传使用的是MultipartHttpServletRequest
解决方案
在进行请求封装的过滤器里判断下,如果是文件上传请求则不做处理,否则使用我们自定义的请求封装器
public class RequestWrapperFilter extends OncePerRequestFilter {
@Override
protected void doFilterInternal(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
HttpServletRequest newRequest=request;
//如果不是文件上传请求则进行封装
if(!StringUtils.startsWithIgnoreCase(request.getContentType(), "multipart/")){
RequestWrapper requestWrapper=new RequestWrapper(request);
newRequest=requestWrapper;
}
filterChain.doFilter(newRequest,response);
}
}
自定义的封装器代码如下,主要是为了解决请求体不能多次获取的问题。结果就是这个让我吃了个大亏
public class RequestWrapper extends HttpServletRequestWrapper {
/**
* 保存流
*/
private final byte[] requestBody;
/**
* Constructs a request object wrapping the given request.
*
* @param request The request to wrap
* @throws IllegalArgumentException if the request is null
*/
@SneakyThrows
public RequestWrapper(HttpServletRequest request) throws IOException {
super(request);
requestBody = StreamUtils.copyToByteArray(request.getInputStream());
}
@Override
public ServletInputStream getInputStream() {
final ByteArrayInputStream basic = new ByteArrayInputStream(requestBody);
return new ServletInputStream() {
@Override
public int read() {
return basic.read();
}
@Override
public boolean isFinished() {
return false;
}
@Override
public boolean isReady() {
return false;
}
@Override
public void setReadListener(ReadListener listener) {
/*
不需要使用读取监听
*/
}
};
}
@Override
public BufferedReader getReader(){
return new BufferedReader(new InputStreamReader(getInputStream()));
}
}