Undertow 上传多部分文件超过设置值时抛出 RuntimeException [英] Undertow throws RuntimeException when uploading multipart file exceeding the setting value
问题描述
我正在 Spring 指南,但我使用 Undertow 作为嵌入式 servlet 而不是默认的 Tomcat.它奏效了.
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
使用Tomcat内嵌servlet,可以通过捕获SizeLimitExceededException
或MultipartException
With Tomcat embedded servlet, it can be easily handled by catching SizeLimitExceededException
or MultipartException
但是对于 Undertow,它会抛出 RuntimeException 事件我在全局处理程序中捕获它:
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();
}
}
异常信息:
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]
代码如下:
控制器
@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?
任何帮助将不胜感激
推荐答案
也许它能够在某些特定情况下提供帮助.
Maybe it is able to help in some particular case.
我在逆流和异常处理方面也有同样的问题.
I have the same problem with undertow and exception handling.
我的情况有点不同,我也有 spring-security,所以当其中一些尝试从请求中读取信息时,spring-security 过滤器会导致像 RequestTooBigException
这样的异常.
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.
作为一种解决方案,我使用了一个额外的过滤器,该过滤器添加在导致该异常的第一个安全过滤器之前.(对我来说是 BearerTokenAuthenticationFilter.class
)
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.
有我的简化安全配置:
@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();
}
}
这篇关于Undertow 上传多部分文件超过设置值时抛出 RuntimeException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!