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 b79e147d43e..015ace3c5eb 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 @@ -43,6 +43,7 @@ import org.springframework.web.servlet.DispatcherServlet; * * @author Greg Turnquist * @author Josh Long + * @author Toshiaki Maki */ @Configuration @ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class, @@ -66,7 +67,9 @@ public class MultipartAutoConfiguration { @Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME) @ConditionalOnMissingBean(MultipartResolver.class) public StandardServletMultipartResolver multipartResolver() { - return new StandardServletMultipartResolver(); + StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver(); + multipartResolver.setResolveLazily(multipartProperties.isResolveLazily()); + return multipartResolver; } } 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 index e7ebe15ef45..01ecc8cf369 100644 --- 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 @@ -42,6 +42,7 @@ import org.springframework.util.StringUtils; * {@literal String} variants that accept {@literal Kb} or {@literal Mb} suffixes. * * @author Josh Long + * @author Toshiaki Maki * @since 1.1.0 */ @ConfigurationProperties(prefix = "spring.http.multipart", ignoreUnknownFields = false) @@ -75,6 +76,12 @@ public class MultipartProperties { */ private String fileSizeThreshold = "0"; + /** + * Whether to resolve the multipart request lazily at the time of file or parameter + * access. + */ + private boolean resolveLazily = false; + public boolean getEnabled() { return this.enabled; } @@ -115,6 +122,14 @@ public class MultipartProperties { this.fileSizeThreshold = fileSizeThreshold; } + public boolean isResolveLazily() { + return resolveLazily; + } + + public void setResolveLazily(boolean resolveLazily) { + this.resolveLazily = resolveLazily; + } + /** * Create a new {@link MultipartConfigElement} using the properties. * @return a new {@link MultipartConfigElement} configured using there properties 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 409c220d95a..943ba048062 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 @@ -40,6 +40,7 @@ import org.springframework.http.client.ClientHttpRequest; import org.springframework.http.client.ClientHttpResponse; import org.springframework.http.client.HttpComponentsClientHttpRequestFactory; import org.springframework.stereotype.Controller; +import org.springframework.test.util.ReflectionTestUtils; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.client.RestTemplate; @@ -59,6 +60,7 @@ import static org.mockito.Mockito.mock; * @author Dave Syer * @author Josh Long * @author Ivan Sopov + * @author Toshiaki Maki */ public class MultipartAutoConfigurationTests { @@ -188,6 +190,20 @@ public class MultipartAutoConfigurationTests { .isNotInstanceOf(StandardServletMultipartResolver.class); } + @Test + public void configureResolveLazily() { + this.context = new AnnotationConfigEmbeddedWebApplicationContext(); + EnvironmentTestUtils.addEnvironment(this.context, + "spring.http.multipart.resolve-lazily=true"); + this.context.register(ContainerWithNothing.class, BaseConfiguration.class); + this.context.refresh(); + StandardServletMultipartResolver multipartResolver = this.context + .getBean(StandardServletMultipartResolver.class); + boolean resolveLazily = (Boolean) ReflectionTestUtils.getField(multipartResolver, + "resolveLazily"); + assertThat(resolveLazily).isTrue(); + } + private void verify404() throws Exception { HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(); ClientHttpRequest request = requestFactory.createRequest( diff --git a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc index 34696cf99d1..67c67cc8f56 100644 --- a/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc +++ b/spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc @@ -283,6 +283,7 @@ content into your application; rather pick only the properties that you need. spring.http.multipart.location= # Intermediate location of uploaded files. spring.http.multipart.max-file-size=1Mb # Max file size. Values can use the suffixed "MB" or "KB" to indicate a Megabyte or Kilobyte size. spring.http.multipart.max-request-size=10Mb # Max request size. Values can use the suffixed "MB" or "KB" to indicate a Megabyte or Kilobyte size. + spring.http.multipart.resolve-lazily=false # Whether to resolve the multipart request lazily at the time of file or parameter access. # JACKSON ({sc-spring-boot-autoconfigure}/jackson/JacksonProperties.{sc-ext}[JacksonProperties]) spring.jackson.date-format= # Date format string or a fully-qualified date format class name. For instance `yyyy-MM-dd HH:mm:ss`.