Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
174 views
in Technique[技术] by (71.8m points)

java - Spring Boot: ClassNotFoundException when configuring maxUploadSize of CommonMultipartResolver

I'm using Spring Boot for my web application and I'm trying to configure the maxUploadSize of Spring's CommonMultipartResolver. Currently, it seems to be limited by a Spring (?) default size of 1 MB. The upload is done through a REST interface, and the method signature looks like this:

@RequestMapping(value = "/upload", method = RequestMethod.POST)
public void uploadFile(@RequestParam("file") MultipartFile file, HttpServletRequest request)

Everytime I try to upload a bigger file, a FileSizeLimitExceededException is thrown:

org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field file exceeds its maximum permitted size of 1048576 bytes.
    at org.apache.tomcat.util.http.fileupload.FileUploadBase$FileItemIteratorImpl$FileItemStreamImpl$1.raiseError(FileUploadBase.java:637)
    at org.apache.tomcat.util.http.fileupload.util.LimitedInputStream.checkLimit(LimitedInputStream.java:76)
    at org.apache.tomcat.util.http.fileupload.util.LimitedInputStream.read(LimitedInputStream.java:135)
    at java.io.FilterInputStream.read(FilterInputStream.java:107)
    at org.apache.tomcat.util.http.fileupload.util.Streams.copy(Streams.java:99)
    at org.apache.tomcat.util.http.fileupload.util.Streams.copy(Streams.java:68)
    at org.apache.tomcat.util.http.fileupload.FileUploadBase.parseRequest(FileUploadBase.java:296)
    at org.apache.catalina.connector.Request.parseParts(Request.java:2737)
    at org.apache.catalina.connector.Request.parseParameters(Request.java:3096)
    at org.apache.catalina.connector.Request.getParameter(Request.java:1145)
    at org.apache.catalina.connector.RequestFacade.getParameter(RequestFacade.java:382)
    at javax.servlet.ServletRequestWrapper.getParameter(ServletRequestWrapper.java:140)
    at javax.servlet.ServletRequestWrapper.getParameter(ServletRequestWrapper.java:140)
    at javax.servlet.ServletRequestWrapper.getParameter(ServletRequestWrapper.java:140)
    at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:70)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
    at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:154)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:110)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:57)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:50)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:192)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:160)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:109)
    at org.springframework.boot.context.web.ErrorPageFilter.access$000(ErrorPageFilter.java:59)
    at org.springframework.boot.context.web.ErrorPageFilter$1.doFilterInternal(ErrorPageFilter.java:88)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.springframework.boot.context.web.ErrorPageFilter.doFilter(ErrorPageFilter.java:101)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:501)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
    at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1040)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:607)
    at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:744)

Things I have tried, but did not work:

Setting Tomcat properties

Since my web app is running on Tomcat (not the embedded one, but a separate external one), I tried configuring the size by changing the Tomcat configuration as is described here. Unfortunately, this has no effect, as the max upload size still remains at 1 MB.

Configuring Spring's CommonMultipartResolver by annotation

Since the value of 1MB seems to come from the CommonMultipartResolver (I can see that the value of 1MB is set when debugging), I tried configuring Spring via annotation like this:

@Configuration 
public class CoreConfig {

    @Bean
    public CommonsMultipartResolver commonsMultipartResolver() {
    CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
    multipartResolver.setMaxUploadSize(50 * 1024 * 1024);
    return multipartResolver;
    }

}

But when I start up Tomcat, the following exception is thrown:

Caused by: java.lang.NoClassDefFoundError: org/apache/commons/fileupload/FileItemFactory
    at myapp.server.CoreConfig.commonsMulipartResolver(CoreConfig.java:40)
    at myapp.server.CoreConfig$$EnhancerBySpringCGLIB$$8b64a88.CGLIB$commonsMulipartResolver$3(<generated>)
    at myapp.server.CoreConfig$$EnhancerBySpringCGLIB$$8b64a88$$FastClassBySpringCGLIB$$ac8c6ee5.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invokeSuper(MethodProxy.java:228)
    at org.springframework.context.annotation.ConfigurationClassEnhancer$BeanMethodInterceptor.intercept(ConfigurationClassEnhancer.java:312)
    at myapp.server.CoreConfig$$EnhancerBySpringCGLIB$$8b64a88.commonsMulipartResolver(<generated>)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:166)
    ... 27 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.apache.commons.fileupload.FileItemFactory
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1720)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1571)

Configuration via XML

Instead of an annotation-driven configuration, I tried a configuration via XML similar to this posting, but I'm getting the same ClassNotFoundException as above.

Additional Info

Spring Boot Starter 1.1.9

Tomcat 7.0.54

Pom.xml of the server

<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>mygroup</groupId>
    <artifactId>myapp.server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.1.9.RELEASE</version>
    </parent>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>17.0</version>
        </dependency>
        <dependency>
      

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

You are making it way to complex.

Just add spring.http.multipart.maxFileSize to your application.properties file and well that is it. No need to use xml or explicitly define a MultipartResolver.

spring.http.multipart.maxFileSize=10MB   

This is explained in the section about file uploads in the Spring Boot Reference Guide.

For all properties check the MultipartProperties class. The other properties supported are spring.http.multipart.location, spring.http.multipart.maxRequestSize and spring.http.multipart.fileSizeThreshold.

The ClassNotFoundException is due to the fact that Spring Boot uses the default Servlet 3.0 support for file uploads NOT commons-fileupload. So if you want to use that, you would have to explicitly add the dependency for it. And ofcourse the spring.http.multipart.* properties don't work anymore in that case.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...