问题
I'm running the complete version of Spring boot Upload file guide at Spring Guide, but I used Undertow as embedded servlet instead of Tomcat default. And it worked.
When I try to upload file with size larger than the value in config file
spring.http.multipart.max-file-size=128KB
spring.http.multipart.max-request-size=128KB
It raises exception. That is expected behavior
With Tomcat embedded servlet, it can be easily handled by catching SizeLimitExceededException or MultipartException
But with Undertow, it throws RuntimeException event I catch it in global handler:
@ControllerAdvice
public class GlobalControllerExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler({RuntimeException.class, Exception.class, IOException.class})
ResponseEntity<?> handleControllerException(Exception exc, HttpServletRequest request, Throwable ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
}
}
The Exception message:
java.lang.RuntimeException: java.io.IOException: UT000020: Connection terminated as request was larger than 131072
at io.undertow.servlet.spec.HttpServletRequestImpl.parseFormData(HttpServletRequestImpl.java:779) ~[undertow-servlet-1.4.20.Final.jar:1.4.20.Final]
at io.undertow.servlet.spec.HttpServletRequestImpl.getParameter(HttpServletRequestImpl.java:653) ~[undertow-servlet-1.4.20.Final.jar:1.4.20.Final]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:75) ~[spring-web-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.12.RELEASE.jar:4.3.12.RELEASE]
Here is the codes:
The controller
@PostMapping("/")
public String handleFileUpload(@RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
storageService.store(file);
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded " + file.getOriginalFilename() + "!");
return "redirect:/";
}
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-uploading-files</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.8.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-undertow</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<version>1.3.0.RELEASE</version>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
Anyone get the same problem with me? How can I catch the exception when maximum file size upload is exceeded?
Any help would be greatly appreciated
回答1:
Maybe it is able to help in some particular case.
I have the same problem with undertow and exception handling.
My case is a little bit different, I also have spring-security, so the exceptions like RequestTooBigException are caused in spring-security filters when some of them try to read information from the request.
As a solution, I use an additional filter that is added before the first security filter that is caused that exception. (For my it is BearerTokenAuthenticationFilter.class)
There is an additional filter that handles these exceptions:
@Component
@Slf4j
public class SecurityRequestToBigExceptionHandlerFilter extends OncePerRequestFilter {
@Override
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
FilterChain filterChain) throws ServletException, IOException {
try {
filterChain.doFilter(request, response);
} catch (IllegalStateException | RequestTooBigException | MultiPartParserDefinition.FileTooLargeException ex) {
if (ex instanceof RequestTooBigException
|| ex instanceof MultiPartParserDefinition.FileTooLargeException) {
writeResponse(response, ex);
return;
}
Throwable causeException = ex.getCause();
if (nonNull(causeException)
&& (causeException instanceof RequestTooBigException
|| causeException instanceof MultiPartParserDefinition.FileTooLargeException)) {
writeResponse(response, causeException);
return;
}
throw ex;
}
}
private void writeResponse(HttpServletResponse response, Throwable ex) throws IOException {
log.debug("Handle RequestToBig Exception with {}", ex.getMessage());
response.setStatus(HttpStatus.BAD_REQUEST.value());
response.getWriter().write(ex.getMessage());
}
}
Next what we need to change is security configuration.
There is my simplified security config:
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private final SecurityRequestToBigExceptionHandlerFilter requestToBigExceptionHandlerFilter;
@Override
public void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(requestToBigExceptionHandlerFilter, BearerTokenAuthenticationFilter.class)
.csrf().disable()
.cors()
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2ResourceServer().jwt();
}
}
来源:https://stackoverflow.com/questions/46968098/undertow-throws-runtimeexception-when-uploading-multipart-file-exceeding-the-set