diff --git a/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsMultipartResolver.java b/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsMultipartResolver.java index eed600aff0..b6911fe981 100644 --- a/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsMultipartResolver.java +++ b/spring-web/src/main/java/org/springframework/web/multipart/commons/CommonsMultipartResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2021 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. @@ -16,7 +16,10 @@ package org.springframework.web.multipart.commons; +import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; @@ -27,7 +30,9 @@ import org.apache.commons.fileupload.FileUpload; import org.apache.commons.fileupload.FileUploadBase; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.servlet.ServletFileUpload; +import org.apache.commons.fileupload.servlet.ServletRequestContext; +import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.web.context.ServletContextAware; import org.springframework.web.multipart.MaxUploadSizeExceededException; @@ -41,7 +46,11 @@ import org.springframework.web.util.WebUtils; /** * Servlet-based {@link MultipartResolver} implementation for * Apache Commons FileUpload - * 1.2 or above. + * 1.2 or above. This resolver variant delegates to a local FileUpload library + * within the application, providing maximum portability across Servlet containers. + * + *
Commons FileUpload traditionally parses POST requests with any "multipart/" type. + * Supported HTTP methods may be customized through {@link #setSupportedMethods}. * *
Provides "maxUploadSize", "maxInMemorySize" and "defaultEncoding" settings as * bean properties (inherited from {@link CommonsFileUploadSupport}). See corresponding @@ -52,19 +61,29 @@ import org.springframework.web.util.WebUtils; * Needs to be initialized either by an application context or * via the constructor that takes a ServletContext (for standalone usage). * + *
Note: The common alternative is
+ * {@link org.springframework.web.multipart.support.StandardServletMultipartResolver},
+ * delegating to the Servlet container's own multipart parser, with configuration to
+ * happen at the container level and potentially with container-specific limitations.
+ *
* @author Trevor D. Cook
* @author Juergen Hoeller
* @since 29.09.2003
* @see #CommonsMultipartResolver(ServletContext)
* @see #setResolveLazily
+ * @see #setSupportedMethods
* @see org.apache.commons.fileupload.servlet.ServletFileUpload
* @see org.apache.commons.fileupload.disk.DiskFileItemFactory
+ * @see org.springframework.web.multipart.support.StandardServletMultipartResolver
*/
public class CommonsMultipartResolver extends CommonsFileUploadSupport
implements MultipartResolver, ServletContextAware {
private boolean resolveLazily = false;
+ @Nullable
+ private Set When configured as a Spring property value,
+ * this can be a comma-separated String: e.g. "POST,PUT".
+ * @since 5.3.9
+ */
+ public void setSupportedMethods(String... supportedMethods) {
+ this.supportedMethods = new HashSet<>(Arrays.asList(supportedMethods));
+ }
+
/**
* Initialize the underlying {@code org.apache.commons.fileupload.servlet.ServletFileUpload}
* instance. Can be overridden to use a custom subclass, e.g. for testing purposes.
@@ -122,7 +152,10 @@ public class CommonsMultipartResolver extends CommonsFileUploadSupport
@Override
public boolean isMultipart(HttpServletRequest request) {
- return ServletFileUpload.isMultipartContent(request);
+ return (this.supportedMethods != null ?
+ this.supportedMethods.contains(request.getMethod()) &&
+ FileUploadBase.isMultipartContent(new ServletRequestContext(request)) :
+ ServletFileUpload.isMultipartContent(request));
}
@Override
diff --git a/spring-web/src/test/java/org/springframework/web/multipart/commons/CommonsMultipartResolverTests.java b/spring-web/src/test/java/org/springframework/web/multipart/commons/CommonsMultipartResolverTests.java
index e4aa779da5..e37bb54c02 100644
--- a/spring-web/src/test/java/org/springframework/web/multipart/commons/CommonsMultipartResolverTests.java
+++ b/spring-web/src/test/java/org/springframework/web/multipart/commons/CommonsMultipartResolverTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2019 the original author or authors.
+ * Copyright 2002-2021 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.
@@ -46,6 +46,7 @@ import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.junit.jupiter.api.Test;
import org.springframework.beans.MutablePropertyValues;
+import org.springframework.http.MediaType;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.context.WebApplicationContext;
@@ -71,6 +72,65 @@ import static org.assertj.core.api.Assertions.assertThat;
*/
public class CommonsMultipartResolverTests {
+ @Test
+ public void isMultipartWithDefaultSetting() {
+ CommonsMultipartResolver resolver = new CommonsMultipartResolver();
+
+ MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
+ assertThat(resolver.isMultipart(request)).isFalse();
+
+ request.setContentType(MediaType.MULTIPART_FORM_DATA_VALUE);
+ assertThat(resolver.isMultipart(request)).isTrue();
+
+ request.setContentType(MediaType.MULTIPART_MIXED_VALUE);
+ assertThat(resolver.isMultipart(request)).isTrue();
+
+ request.setContentType(MediaType.MULTIPART_RELATED_VALUE);
+ assertThat(resolver.isMultipart(request)).isTrue();
+
+ request = new MockHttpServletRequest("PUT", "/");
+ assertThat(resolver.isMultipart(request)).isFalse();
+
+ request.setContentType(MediaType.MULTIPART_FORM_DATA_VALUE);
+ assertThat(resolver.isMultipart(request)).isFalse();
+
+ request.setContentType(MediaType.MULTIPART_MIXED_VALUE);
+ assertThat(resolver.isMultipart(request)).isFalse();
+
+ request.setContentType(MediaType.MULTIPART_RELATED_VALUE);
+ assertThat(resolver.isMultipart(request)).isFalse();
+ }
+
+ @Test
+ public void isMultipartWithSupportedMethods() {
+ CommonsMultipartResolver resolver = new CommonsMultipartResolver();
+ resolver.setSupportedMethods("POST", "PUT");
+
+ MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
+ assertThat(resolver.isMultipart(request)).isFalse();
+
+ request.setContentType(MediaType.MULTIPART_FORM_DATA_VALUE);
+ assertThat(resolver.isMultipart(request)).isTrue();
+
+ request.setContentType(MediaType.MULTIPART_MIXED_VALUE);
+ assertThat(resolver.isMultipart(request)).isTrue();
+
+ request.setContentType(MediaType.MULTIPART_RELATED_VALUE);
+ assertThat(resolver.isMultipart(request)).isTrue();
+
+ request = new MockHttpServletRequest("PUT", "/");
+ assertThat(resolver.isMultipart(request)).isFalse();
+
+ request.setContentType(MediaType.MULTIPART_FORM_DATA_VALUE);
+ assertThat(resolver.isMultipart(request)).isTrue();
+
+ request.setContentType(MediaType.MULTIPART_MIXED_VALUE);
+ assertThat(resolver.isMultipart(request)).isTrue();
+
+ request.setContentType(MediaType.MULTIPART_RELATED_VALUE);
+ assertThat(resolver.isMultipart(request)).isTrue();
+ }
+
@Test
public void withApplicationContext() throws Exception {
doTestWithApplicationContext(false);