diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfiguration.java index f4a25b74ac5..c4107dcd3c0 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfiguration.java @@ -16,33 +16,70 @@ package org.springframework.boot.autoconfigure.web; -import javax.servlet.MultipartConfigElement; -import javax.servlet.Servlet; - +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.context.embedded.EmbeddedWebApplicationContext; +import org.springframework.boot.context.embedded.MultipartConfigFactory; +import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.util.StringUtils; import org.springframework.web.multipart.support.StandardServletMultipartResolver; +import javax.servlet.MultipartConfigElement; +import javax.servlet.Servlet; + /** * {@link EnableAutoConfiguration Auto-configuration} for multi-part uploads. Adds a - * {@link StandardServletMultipartResolver} when a {@link MultipartConfigElement} bean is - * defined. The {@link EmbeddedWebApplicationContext} will associated the + * {@link StandardServletMultipartResolver} if none is present, and adds a + * {@link javax.servlet.MultipartConfigElement multipartConfigElement} if none is otherwise defined. + * The {@link EmbeddedWebApplicationContext} will associate the * {@link MultipartConfigElement} bean to any {@link Servlet} beans. - * + *
+ * The {@link javax.servlet.MultipartConfigElement} is a Servlet API that's used to configure how the container handles + * file uploads. By default + * * @author Greg Turnquist + * @author Josh Long */ @Configuration -@ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class }) -@ConditionalOnBean(MultipartConfigElement.class) +@ConditionalOnClass({Servlet.class, StandardServletMultipartResolver.class}) +@EnableConfigurationProperties(MultipartProperties.class) public class MultipartAutoConfiguration { - @Bean - public StandardServletMultipartResolver multipartResolver() { - return new StandardServletMultipartResolver(); - } + @Autowired + private MultipartProperties multipartProperties = new MultipartProperties(); + + @Bean + @ConditionalOnMissingBean + public MultipartConfigElement multipartConfigElement() { + MultipartConfigFactory factory = new MultipartConfigFactory(); + + if (StringUtils.hasText(this.multipartProperties.getFileSizeThreshold())) { + factory.setFileSizeThreshold(this.multipartProperties.getFileSizeThreshold()); + } + + if (StringUtils.hasText(this.multipartProperties.getLocation())) { + factory.setLocation(this.multipartProperties.getLocation()); + } + + if (StringUtils.hasText(this.multipartProperties.getMaxRequestSize())) { + factory.setMaxRequestSize(this.multipartProperties.getMaxRequestSize()); + } + + if (StringUtils.hasText(this.multipartProperties.getMaxFileSize())) { + factory.setMaxFileSize(this.multipartProperties.getMaxFileSize()); + } + + return factory.createMultipartConfig(); + } + + @Bean + @ConditionalOnMissingBean + public StandardServletMultipartResolver multipartResolver() { + return new StandardServletMultipartResolver(); + } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartProperties.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartProperties.java new file mode 100644 index 00000000000..91d8e49bc92 --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/MultipartProperties.java @@ -0,0 +1,80 @@ +/* + * Copyright 2012-2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.autoconfigure.web; + +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * Properties to be used in configuring + * a javax.servlet.MultipartConfigElement. + * + * {@literal multipart.fileSizeThreshold} specifies the size threshold after which files will be written to disk. Default is 0, which means that the file will be written to disk immediately. + * {@literal multipart.location} specifies the directory where files will be stored. The default is "". A common value is to use the system's temporary directory, which can be obtained + * {@literal multipart.maxFileSize} specifies the maximum size permitted for uploaded files. The default is unlimited. + * {@literal multipart.maxRequestSize} specifies the maximum size allowed for {@literal multipart/form-data} requests. + * + * These properties are ultimately passed through {@link org.springframework.boot.context.embedded.MultipartConfigFactory} + * which means you may specify the values using {@literal long} values or using more readable {@literal String} + * variants that accept {@literal KB} or {@literal MB} suffixes. + * + * @author Josh Long + */ +@ConfigurationProperties(prefix = "multipart", ignoreUnknownFields = false) +public class MultipartProperties { + + private String maxFileSize = "1Mb"; + + private String maxRequestSize = "10Mb"; + + private String fileSizeThreshold = null; + + private String location = null; + + public String getMaxFileSize() { + return maxFileSize; + } + + public String getMaxRequestSize() { + return maxRequestSize; + } + + public String getFileSizeThreshold() { + return fileSizeThreshold; + } + + public String getLocation() { + return location; + } + + public void setMaxFileSize(String maxFileSize) { + this.maxFileSize = maxFileSize; + } + + public void setMaxRequestSize(String maxRequestSize) { + this.maxRequestSize = maxRequestSize; + } + + public void setLocation(String location) { + this.location = location; + } + + public void setFileSizeThreshold(String fileSizeThreshold) { + this.fileSizeThreshold = fileSizeThreshold; + } + +} + diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfigurationTests.java index 8e0f4ee0ecd..b7d36931a11 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/DispatcherServletAutoConfigurationTests.java @@ -20,7 +20,7 @@ import javax.servlet.MultipartConfigElement; import org.junit.Test; import org.springframework.beans.factory.UnsatisfiedDependencyException; -import org.springframework.boot.context.embedded.MultiPartConfigFactory; +import org.springframework.boot.context.embedded.MultipartConfigFactory; import org.springframework.boot.context.embedded.ServletRegistrationBean; import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.context.annotation.Bean; @@ -120,7 +120,7 @@ public class DispatcherServletAutoConfigurationTests { @Bean public MultipartConfigElement multipartConfig() { - MultiPartConfigFactory factory = new MultiPartConfigFactory(); + MultipartConfigFactory factory = new MultipartConfigFactory(); factory.setMaxFileSize("128KB"); factory.setMaxRequestSize("128KB"); return factory.createMultipartConfig(); diff --git a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfigurationTests.java b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfigurationTests.java index 5c3f8b55d78..79fd73d4b98 100644 --- a/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfigurationTests.java +++ b/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/web/MultipartAutoConfigurationTests.java @@ -28,6 +28,7 @@ import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletCon import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.core.env.PropertySource; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; @@ -38,15 +39,17 @@ import org.springframework.web.servlet.DispatcherServlet; import org.springframework.web.servlet.config.annotation.EnableWebMvc; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; /** * Tests for {@link MultipartAutoConfiguration}. Tests an empty configuration, no * multipart configuration, and a multipart configuration (with both Jetty and Tomcat). - * + * * @author Greg Turnquist * @author Dave Syer + * @author Josh Long */ public class MultipartAutoConfigurationTests { @@ -67,11 +70,11 @@ public class MultipartAutoConfigurationTests { this.context = new AnnotationConfigEmbeddedWebApplicationContext( ContainerWithNothing.class, BaseConfiguration.class); DispatcherServlet servlet = this.context.getBean(DispatcherServlet.class); - assertNull(servlet.getMultipartResolver()); - assertEquals(0, + assertNotNull(servlet.getMultipartResolver()); + assertEquals(1, this.context.getBeansOfType(StandardServletMultipartResolver.class) .size()); - assertEquals(0, this.context.getBeansOfType(MultipartResolver.class).size()); + assertEquals(1, this.context.getBeansOfType(MultipartResolver.class).size()); } @Configuration @@ -83,11 +86,11 @@ public class MultipartAutoConfigurationTests { this.context = new AnnotationConfigEmbeddedWebApplicationContext( ContainerWithNoMultipartJetty.class, BaseConfiguration.class); DispatcherServlet servlet = this.context.getBean(DispatcherServlet.class); - assertNull(servlet.getMultipartResolver()); - assertEquals(0, + assertNotNull(servlet.getMultipartResolver()); + assertEquals(1, this.context.getBeansOfType(StandardServletMultipartResolver.class) .size()); - assertEquals(0, this.context.getBeansOfType(MultipartResolver.class).size()); + assertEquals(1, this.context.getBeansOfType(MultipartResolver.class).size()); verifyServletWorks(); } @@ -110,10 +113,10 @@ public class MultipartAutoConfigurationTests { ContainerWithNoMultipartTomcat.class, BaseConfiguration.class); DispatcherServlet servlet = this.context.getBean(DispatcherServlet.class); assertNull(servlet.getMultipartResolver()); - assertEquals(0, + assertEquals(1, this.context.getBeansOfType(StandardServletMultipartResolver.class) .size()); - assertEquals(0, this.context.getBeansOfType(MultipartResolver.class).size()); + assertEquals(1, this.context.getBeansOfType(MultipartResolver.class).size()); verifyServletWorks(); } @@ -131,20 +134,36 @@ public class MultipartAutoConfigurationTests { public void containerWithAutomatedMultipartTomcatConfiguration() throws Exception { this.context = new AnnotationConfigEmbeddedWebApplicationContext( ContainerWithEverythingTomcat.class, BaseConfiguration.class); - new RestTemplate().getForObject("http://localhost:" - + this.context.getEmbeddedServletContainer().getPort() + "/", - String.class); + new RestTemplate().getForObject("http://localhost:8080/", String.class); this.context.getBean(MultipartConfigElement.class); assertSame(this.context.getBean(DispatcherServlet.class).getMultipartResolver(), this.context.getBean(StandardServletMultipartResolver.class)); verifyServletWorks(); } + @Test + public void containerWithMultipartConfigDisabled() { + + this.context = new AnnotationConfigEmbeddedWebApplicationContext(); + this.context.getEnvironment().getPropertySources() + .addFirst(new PropertySource