Skip to content

Commit cc0a845

Browse files
committed
Support Part/MultiPartFile arrays in ArgumentResolvers
Prior to this commit, parts of a multipart HTTP request could be injected in @RequestPart and @RequestParam annotated arguments, when using types: * MultipartFile, Collection<MultiPartFile> * javax.servlet.Part, Collection<Part> This commits updates @RequestParam and @RequestPart argument resolvers and now allows the array versions of those types: * Part[] * MultiPartFile[] Note that the MockHtpServletRequest backing tests for standard Servlets implementations now uses a MultiValueMap to store parts (versus a simple hashmap). Issue: SPR-11353
1 parent 7854277 commit cc0a845

File tree

5 files changed

+258
-50
lines changed

5 files changed

+258
-50
lines changed

spring-web/src/main/java/org/springframework/web/method/annotation/RequestParamMethodArgumentResolver.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,6 +23,7 @@
2323
import java.util.Map;
2424
import javax.servlet.ServletException;
2525
import javax.servlet.http.HttpServletRequest;
26+
import javax.servlet.http.Part;
2627

2728
import org.springframework.beans.BeanUtils;
2829
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
@@ -69,6 +70,7 @@
6970
*
7071
* @author Arjen Poutsma
7172
* @author Rossen Stoyanchev
73+
* @author Brian Clozel
7274
* @since 3.1
7375
* @see RequestParamMapMethodArgumentResolver
7476
*/
@@ -174,6 +176,11 @@ else if (isMultipartFileCollection(parameter)) {
174176
Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
175177
arg = multipartRequest.getFiles(name);
176178
}
179+
else if(isMultipartFileArray(parameter)) {
180+
assertIsMultipartRequest(servletRequest);
181+
Assert.notNull(multipartRequest, "Expected MultipartHttpServletRequest: is a MultipartResolver configured?");
182+
arg = multipartRequest.getFiles(name).toArray(new MultipartFile[0]);
183+
}
177184
else if ("javax.servlet.http.Part".equals(parameter.getParameterType().getName())) {
178185
assertIsMultipartRequest(servletRequest);
179186
arg = servletRequest.getPart(name);
@@ -182,6 +189,10 @@ else if (isPartCollection(parameter)) {
182189
assertIsMultipartRequest(servletRequest);
183190
arg = new ArrayList<Object>(servletRequest.getParts());
184191
}
192+
else if (isPartArray(parameter)) {
193+
assertIsMultipartRequest(servletRequest);
194+
arg = RequestPartResolver.resolvePart(servletRequest);
195+
}
185196
else {
186197
arg = null;
187198
if (multipartRequest != null) {
@@ -218,6 +229,16 @@ private boolean isPartCollection(MethodParameter parameter) {
218229
return ((collectionType != null) && "javax.servlet.http.Part".equals(collectionType.getName()));
219230
}
220231

232+
private boolean isPartArray(MethodParameter parameter) {
233+
Class<?> paramType = parameter.getParameterType().getComponentType();
234+
return ((paramType != null) && "javax.servlet.http.Part".equals(paramType.getName()));
235+
}
236+
237+
private boolean isMultipartFileArray(MethodParameter parameter) {
238+
Class<?> paramType = parameter.getParameterType().getComponentType();
239+
return ((paramType != null) && MultipartFile.class.equals(paramType));
240+
}
241+
221242
private Class<?> getCollectionParameterType(MethodParameter parameter) {
222243
Class<?> paramType = parameter.getParameterType();
223244
if (Collection.class.equals(paramType) || List.class.isAssignableFrom(paramType)){
@@ -277,4 +298,11 @@ public RequestParamNamedValueInfo(RequestParam annotation) {
277298
}
278299
}
279300

301+
private static class RequestPartResolver {
302+
303+
public static Object resolvePart(HttpServletRequest servletRequest) throws Exception {
304+
return servletRequest.getParts().toArray(new Part[servletRequest.getParts().size()]);
305+
}
306+
}
307+
280308
}

spring-web/src/test/java/org/springframework/mock/web/test/MockHttpServletRequest.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2014 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -53,6 +53,8 @@
5353

5454
import org.springframework.util.Assert;
5555
import org.springframework.util.LinkedCaseInsensitiveMap;
56+
import org.springframework.util.LinkedMultiValueMap;
57+
import org.springframework.util.MultiValueMap;
5658
import org.springframework.util.StringUtils;
5759

5860
/**
@@ -66,6 +68,7 @@
6668
* @author Mark Fisher
6769
* @author Chris Beams
6870
* @author Sam Brannen
71+
* @author Brian Clozel
6972
* @since 1.0.2
7073
*/
7174
public class MockHttpServletRequest implements HttpServletRequest {
@@ -196,7 +199,7 @@ public class MockHttpServletRequest implements HttpServletRequest {
196199

197200
private boolean requestedSessionIdFromURL = false;
198201

199-
private final Map<String, Part> parts = new LinkedHashMap<String, Part>();
202+
private final MultiValueMap<String, Part> parts = new LinkedMultiValueMap<String, Part>();
200203

201204

202205
// ---------------------------------------------------------------------
@@ -1048,17 +1051,21 @@ public void logout() throws ServletException {
10481051
}
10491052

10501053
public void addPart(Part part) {
1051-
this.parts.put(part.getName(), part);
1054+
this.parts.add(part.getName(), part);
10521055
}
10531056

10541057
@Override
10551058
public Part getPart(String name) throws IOException, IllegalStateException, ServletException {
1056-
return this.parts.get(name);
1059+
return this.parts.getFirst(name);
10571060
}
10581061

10591062
@Override
10601063
public Collection<Part> getParts() throws IOException, IllegalStateException, ServletException {
1061-
return this.parts.values();
1064+
List<Part> result = new LinkedList<Part>();
1065+
for(List<Part> list : this.parts.values()) {
1066+
result.addAll(list);
1067+
}
1068+
return result;
10621069
}
10631070

10641071
}

0 commit comments

Comments
 (0)