我正在使用SpringBoot 2.1.3.RELEASE + thymeleaf + tomcat 8.53嵌入式。我也有一个带有fileupload输入字段的表单。
如在文档中所写,我的DTO bean中具有MultiPartFile,并在application.properties中设置最大文件大小,如下所示:
spring.servlet.multipart.max-file-size=3MB
spring.servlet.multipart.max-request-size=3MB
它(一半)有效,因为如果我加载的文件大于3 mb,应用程序将崩溃,并且浏览器无法发送POST,并且控制器将永远无法到达。.
目前,我解决了一个糟糕的JQuery解决方案,但我想做的是与我拥有的所有其他文件类似的实现,例如:
JAVA BEAN
class Bean {
@NotNull
private String name;
}
胸腺
<form id="msform" action="" th:action="@{/save-fornitore}" th:object="${user}" method="post" enctype="multipart/form-data">
<input type="text" th:field="*{name}" th:text="${name}"></input>
<span th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span>
<input type="submit"></input>
</form>
以及 messages.properties 文件中的一些自定义消息
NotNull.user.name=*NOME: \u0020 Il campo \u00E8 obbligatorio; \u0020\u0020
我已阅读到这是tomcat连接重置的问题;我找到了一个示例,但它仅适用于以前版本的SpringBoot:
@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbedded() {
TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();
tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> {
if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol<?>)) {
//-1 means unlimited
((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1);
}
});
return tomcat;
}
我无法用SpringBoot 2.1.3做同样的事情。我想在处理其他字段时将错误绑定,如果文件太大,请返回表单页面。
我找到了添加该控制器返回错误页面的方法:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MultipartException.class)
public String handleError1(MultipartException e, RedirectAttributes redirectAttributes) {
// redirectAttributes.addFlashAttribute("message", e.getCause().getMessage());
return "redirect:/errorPage";
}
}
但是这种简单的重定向将流程重定向到一个空页面(至少我可以添加一条错误消息),从而丢失了论坛发布的所有数据(除了文件,我还有其他50个属性。)。
我什至发现可以在springboot 2.0上设置tomcat swallowSize属性,如下所示:
server.tomcat.max-swallow-size=-1
但是这些都没有帮助我做我想做的事。
P.S .:这个论坛发生了什么?几年前,它挽救了我的生命不止一次,但最近平均答复是每20个问题中就有1个。
------------------------------- 更新2 ------- ------------------------------
好吧,让我们重新启动一些代码示例和屏幕截图。首先,我正在使用JPA,SpringBoot 2.1.3,Thymeleaf。比起我简单的DTO调用 UserDTO
@Data //lombok
public class UserDTO {
@Size(min=10, max=15)
private String name;
private MultipartFile file;
}
在我的资源/模板中,我有一个具有以下格式的welcome.html页面:
<!DOCTYPE html>
<html xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
xmlns:th="http://www.thymeleaf.org">
<head><title>Form page</title></head>
<form id="myform" action="" th:action="@{/save-user}" th:object="${user}" method="post" enctype="multipart/form-data">
<input type="text" th:field="*{name}" />
<p th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></p>
<input type="file" th:field="*{file}" />
<p th:if="${#fields.hasErrors('file')}" th:errors="*{file}"></p>
<input type="submit" />
</form>
我的主控制器:
@GetMapping("/")
String index(Model model) {
model.addAttribute("user", new UserDTO());
return "welcome";
}
@PostMapping("/save-user")
String saveUser(@Valid @ModelAttribute("user") UserDTO user, BindingResult result, Model model) {
if (result.hasErrors()) {
System.out.println("ERROR");
model.addAttribute("user", user);
return "welcome";
}
return success; // ipotetic success page
}
我的application.properties设置为要上传3 MB的文件(默认值为1MB):
spring.servlet.multipart.max-file-size=3MB
spring.servlet.multipart.max-request-size=3MB
我还为每个Bean属性设置了一个自定义错误消息,例如 messages.properties 中的示例:
Size.user.name=Name Must be between 10 and 15
很明显,我的表单更大,但是问题只在multipartfile上,而这个例子基本上是完美的。示例表单如下所示:
如果我用较少(或更多)的字符数填充名称,并提交表单->操作'save-user'已丰富,则'user'ModelAttribute正在验证,并且如果有错误,控制器将返回同一页面,先前插入的数据已得到处理,并且错误显示如下:
相反,如果我尝试加载大于3MB的文件,则会导致连接崩溃。控制器无法到达,错误是:
org.apache.tomcat.util.http.fileupload.FileUploadBase$
SizeLimitExceededException: the request was rejected because its size (7529964) exceeds the configured maximum (3145728)
at org.apache.tomcat.util.http.fileupload.FileUploadBase$FileItemIteratorImpl.<init>(FileUploadBase.java:808) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.tomcat.util.http.fileupload.FileUploadBase.getItemIterator(FileUploadBase.java:256) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:280) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.connector.Request.parseParts(Request.java:2846) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.connector.Request.parseParameters(Request.java:3185) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.connector.Request.getParameter(Request.java:1116) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:381) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:84) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:200) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-5.1.5.RELEASE.jar:5.1.5.RELEASE]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.16.jar:9.0.16]
在我的途中,我找到了2个解决方案,但两者都很粗糙:
1)如我的第一篇文章所述,配置tomcat吞咽大小:
spring.servlet.multipart.max-file-size=-3MB
spring.servlet.multipart.max-request-size=3MB
server.tomcat.max-swallow-size=-1 // this
并添加了控制器建议:
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(MultipartException.class)
public String handleError1(MultipartException e, RedirectAttributes redirectAttributes) {
return "redirect:/somePage";
}
}
通过这种解决方法,我可以返回错误页面,但我会丢失用户插入的所有数据和错误消息(以复杂的形式,对于用户查看他的错误位置以及如何正确输入很有用)
2)使用自定义验证器疯狂配置雄猫:
spring.servlet.multipart.max-file-size=-1
spring.servlet.multipart.max-request-size=-1
server.tomcat.max-swallow-size=-1
并实现:
public class MultiPartFileValidator implements ConstraintValidator <FileValidator, MultipartFile> {
@Override
public boolean isValid(MultipartFile file, ConstraintValidatorContext context) {
if ( ( (file.getSize() / 1024) / 1024) < 1) return true;
else return false;
}
}
这样,如果我将 @FileValidator 批注放入DTO中的MultiPartFile中,则验证效果会很好,但是如果用户不小心上传了电影而不是其简历,我们将等待一些....
我想我没有比这更清楚了。
P.S .:这种经典图形真的很酷,清晰,简单。全新的产品胜于饥饿和疾病。图形更少..更多内容..
谢谢