Skip to content

Commit cc4faa5

Browse files
bclozelPhillip Webb
authored andcommitted
Fix standard multipart binding + Polish
Fixing standard multipart binding when multiple parts share the same name. Uncomment previously @ignored tests now that Jetty supports Servlet 3.0 spec. Issue: SPR-10591
1 parent 6f2004f commit cc4faa5

File tree

3 files changed

+33
-11
lines changed

3 files changed

+33
-11
lines changed

spring-web/src/main/java/org/springframework/web/bind/support/WebRequestDataBinder.java

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,17 @@
1717
package org.springframework.web.bind.support;
1818

1919
import java.io.IOException;
20+
import java.util.List;
21+
import java.util.Map;
2022

2123
import javax.servlet.ServletException;
2224
import javax.servlet.http.HttpServletRequest;
2325
import javax.servlet.http.Part;
2426

2527
import org.springframework.beans.MutablePropertyValues;
2628
import org.springframework.util.ClassUtils;
29+
import org.springframework.util.LinkedMultiValueMap;
30+
import org.springframework.util.MultiValueMap;
2731
import org.springframework.util.StringUtils;
2832
import org.springframework.validation.BindException;
2933
import org.springframework.web.bind.WebDataBinder;
@@ -119,7 +123,7 @@ public void bind(WebRequest request) {
119123
}
120124
else if (ClassUtils.hasMethod(HttpServletRequest.class, "getParts")) {
121125
HttpServletRequest serlvetRequest = ((NativeWebRequest) request).getNativeRequest(HttpServletRequest.class);
122-
new Servlet3MultipartHelper().bindParts(serlvetRequest, mpvs);
126+
new Servlet3MultipartHelper(isBindEmptyMultipartFiles()).bindParts(serlvetRequest, mpvs);
123127
}
124128
}
125129
doBind(mpvs);
@@ -154,10 +158,30 @@ private boolean isMultipartRequest(WebRequest request) {
154158
*/
155159
private static class Servlet3MultipartHelper {
156160

161+
private final boolean bindEmptyMultipartFiles;
162+
163+
164+
public Servlet3MultipartHelper(boolean bindEmptyMultipartFiles) {
165+
this.bindEmptyMultipartFiles = bindEmptyMultipartFiles;
166+
}
167+
168+
157169
public void bindParts(HttpServletRequest request, MutablePropertyValues mpvs) {
158170
try {
159-
for(Part part : request.getParts()) {
160-
mpvs.add(part.getName(), part);
171+
MultiValueMap<String, Part> map = new LinkedMultiValueMap<String, Part>();
172+
for (Part part : request.getParts()) {
173+
map.add(part.getName(), part);
174+
}
175+
for (Map.Entry<String, List<Part>> entry: map.entrySet()) {
176+
if (entry.getValue().size() == 1) {
177+
Part part = entry.getValue().get(0);
178+
if (this.bindEmptyMultipartFiles || part.getSize() > 0) {
179+
mpvs.add(entry.getKey(), part);
180+
}
181+
}
182+
else {
183+
mpvs.add(entry.getKey(), entry.getValue());
184+
}
161185
}
162186
}
163187
catch (IOException ex) {

spring-web/src/test/java/org/springframework/web/bind/support/WebRequestDataBinderIntegrationTests.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
import javax.servlet.MultipartConfigElement;
2323
import javax.servlet.ServletException;
24-
import javax.servlet.annotation.MultipartConfig;
2524
import javax.servlet.http.HttpServlet;
2625
import javax.servlet.http.HttpServletRequest;
2726
import javax.servlet.http.HttpServletResponse;
@@ -38,7 +37,6 @@
3837
import org.springframework.core.io.Resource;
3938
import org.springframework.http.MediaType;
4039
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
41-
import org.springframework.mock.web.test.MockMultipartFile;
4240
import org.springframework.util.LinkedMultiValueMap;
4341
import org.springframework.util.MultiValueMap;
4442
import org.springframework.util.SocketUtils;
@@ -109,7 +107,7 @@ public void testPartsBinding() {
109107
partsServlet.setBean(bean);
110108

111109
MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
112-
MockMultipartFile firstPart = new MockMultipartFile("fileName", "aValue".getBytes());
110+
Resource firstPart = new ClassPathResource("/org/springframework/http/converter/logo.jpg");
113111
parts.add("firstPart", firstPart);
114112
parts.add("secondPart", "secondValue");
115113

@@ -134,7 +132,7 @@ public void testPartListBinding() {
134132
template.postForLocation(baseUrl + "/partlist", parts);
135133

136134
assertNotNull(bean.getPartList());
137-
assertEquals(parts.size(), bean.getPartList().size());
135+
assertEquals(parts.get("partList").size(), bean.getPartList().size());
138136
}
139137

140138

spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestPartIntegrationTests.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@
1919
import java.net.URI;
2020
import java.util.Arrays;
2121

22+
import javax.servlet.MultipartConfigElement;
23+
2224
import org.eclipse.jetty.server.Server;
2325
import org.eclipse.jetty.servlet.ServletContextHandler;
2426
import org.eclipse.jetty.servlet.ServletHolder;
2527
import org.junit.AfterClass;
2628
import org.junit.Before;
2729
import org.junit.BeforeClass;
28-
import org.junit.Ignore;
2930
import org.junit.Test;
3031
import org.springframework.context.annotation.Bean;
3132
import org.springframework.context.annotation.Configuration;
@@ -62,6 +63,7 @@
6263
* Test access to parts of a multipart request with {@link RequestPart}.
6364
*
6465
* @author Rossen Stoyanchev
66+
* @author Brian Clozel
6567
*/
6668
public class RequestPartIntegrationTests {
6769

@@ -91,10 +93,9 @@ public static void startServer() throws Exception {
9193
ServletHolder standardResolverServlet = new ServletHolder(DispatcherServlet.class);
9294
standardResolverServlet.setInitParameter("contextConfigLocation", config.getName());
9395
standardResolverServlet.setInitParameter("contextClass", AnnotationConfigWebApplicationContext.class.getName());
96+
standardResolverServlet.getRegistration().setMultipartConfig(new MultipartConfigElement(""));
9497
handler.addServlet(standardResolverServlet, "/standard-resolver/*");
9598

96-
// TODO: add Servlet 3.0 test case without MultipartResolver
97-
9899
server.setHandler(handler);
99100
server.start();
100101
}
@@ -123,7 +124,6 @@ public void commonsMultipartResolver() throws Exception {
123124
}
124125

125126
@Test
126-
@Ignore("jetty 6.1.9 doesn't support Servlet 3.0")
127127
public void standardMultipartResolver() throws Exception {
128128
testCreate(baseUrl + "/standard-resolver/test");
129129
}

0 commit comments

Comments
 (0)