文件上传大小限制问题 – 从网页上传70MB大小的CSV失败原因分析和解决

内容纲要

问题

从网页上传70MB大小的CSV失败

报错日志:

org.apache.http.client.ClientProtocolException
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:187)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
......

Caused by: org.apache.http.client.NonRepeatableRequestException: Cannot retry request with a non-repeatable request entity
    at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:108)
    at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
    ... 124 more
Caused by: java.net.SocketException: Connection reset by peer: socket write error
    at java.net.SocketOutputStream.socketWrite0(Native Method)
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:111)
    at java.net.SocketOutputStream.write(SocketOutputStream.java:155)
    at org.apache.http.impl.io.SessionOutputBufferImpl.streamWrite(SessionOutputBufferImpl.java:124)
......

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.NullPointerException
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:681)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
......

原因分析

项目技术:前后端均使用SpringBoot(1.5.22.RELEASE)+Thymeleaf模板引擎搭建。

具体原因:

1、前端模块A 和 后端模块B在application.properties配置文件中存在以下配置

## springboot文件传输大小限制
# maxFileSize 单个数据大小
spring.servlet.multipart.maxFileSize = 500MB
# maxRequestSize 是总数据大小
spring.servlet.multipart.maxRequestSize=500MB

spring.http.multipart.maxFileSize=1024MB
spring.http.multipart.maxRequestSize=1024MB

# tomcat单个文件大小限制
spring.servlet.multipart.max-file-size=1024MB
# tomcat总文件大小限制
spring.servlet.multipart.max-request-size=1024MB

2、A、B模块在各自的SpringApplication启动类中,也存在上传文件大小配置

@SpringBootApplication
@ComponentScan(basePackages={"com.xxx.xxx", "com.xxx.xxx2"})
@ServletComponentScan(basePackages = "com.xxx.xxx")
public class XXXApplication {
    public static void main(String[] args) {
        SpringApplication.run(XXXApplication.class, args);
    }
    @Bean
    public MultipartConfigElement multipartConfigElement() {
        MultipartConfigFactory factory = new MultipartConfigFactory();
        // 允许上传的文件最大值
        factory.setMaxFileSize("1024MB"); //KB,MB
        // 设置总上传数据总大小
        factory.setMaxRequestSize("1024MB");
        return factory.createMultipartConfig();
    }
}

结论:

Spring Boot 在启动时会先加载 application.propertiesapplication.yml 中的配置,然后再加载带有 @Configuration 的配置类(如你的启动类)中的Bean。因此,如果你的 MultipartConfigElement Bean中的配置与 application.properties 中的配置不一致,那么会以 MultipartConfigElement Bean中的配置为准。

这是因为Spring Boot的自动配置机制,它会首先加载 application.properties 中的配置,然后在加载Bean时检查这些配置。如果在Bean中找到了与 application.properties 中不一致的配置,那么Spring Boot会使用Bean中的配置覆盖 application.properties 中的配置。

如果你的Spring Boot版本是2.0及以上
然而,你的代码和配置中似乎存在一些混淆。从 Spring Boot 2.0 开始,spring.http.multipart.* 已被 spring.servlet.multipart.* 替代,所以在新版本的Spring Boot应用中,你应该使用后者。因此,如果你的Spring Boot版本是2.0及以上,应该使用以下的配置:

# tomcat单个文件大小限制
spring.servlet.multipart.max-file-size=1024MB
# tomcat总文件大小限制
spring.servlet.multipart.max-request-size=1024MB

然后在你的启动类中创建一个 MultipartConfigElement Bean

@Bean
public MultipartConfigElement multipartConfigElement() {
    MultipartConfigFactory factory = new MultipartConfigFactory();
    // 单个数据大小
    factory.setMaxFileSize("1024MB");
    // 总上传数据大小
    factory.setMaxRequestSize("1024MB");
    return factory.createMultipartConfig();
}

这样,无论你的Spring Boot版本是多少,都可以保证文件上传大小的配置是正确的。

解决方案

1、确认application.properties中的tomcat配置的文件大小
SpringBoot 1.x版本

# tomcat单个文件大小限制
spring.http.multipart.maxFileSize=1024MB
# tomcat总文件大小限制
spring.http.multipart.maxRequestSize=1024MB


SpringBoot 2.x版本

# tomcat单个文件大小限制
spring.servlet.multipart.max-file-size=1024MB
# tomcat总文件大小限制
spring.servlet.multipart.max-request-size=1024MB

2、检查Application启动类中或其他配置类位置中的@Bean注解,public MultipartConfigElement multipartConfigElement()配置

@Bean
public MultipartConfigElement multipartConfigElement() {
    MultipartConfigFactory factory = new MultipartConfigFactory();
    // 允许上传的文件最大值
    factory.setMaxFileSize("1024MB"); //KB,MB
    // 设置总上传数据总大小
    factory.setMaxRequestSize("1024MB");
    return factory.createMultipartConfig();
}

调整为合适的大小即可。
3、如果是从一个前端模块A上传到另一个后端模块B,需要注意A、B模块都需要注意上传文件大小的配置。

Leave a Comment

您的电子邮箱地址不会被公开。 必填项已用*标注

close
arrow_upward