SPR-2784: Support MultipartFile-array property
This commit is contained in:
parent
ae8c053568
commit
66a799552f
|
|
@ -64,7 +64,6 @@ public class LinkedMultiValueMap<K, V> implements MultiValueMap<K, V> {
|
|||
this.targetMap = new LinkedHashMap<K, List<V>>(otherMap);
|
||||
}
|
||||
|
||||
|
||||
// MultiValueMap implementation
|
||||
|
||||
public void add(K key, V value) {
|
||||
|
|
@ -87,6 +86,19 @@ public class LinkedMultiValueMap<K, V> implements MultiValueMap<K, V> {
|
|||
this.targetMap.put(key, values);
|
||||
}
|
||||
|
||||
public void setAll(Map<K, V> values) {
|
||||
for (Entry<K, V> entry : values.entrySet()) {
|
||||
set(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public Map<K, V> toSingleValueMap() {
|
||||
LinkedHashMap<K, V> singleValueMap = new LinkedHashMap<K,V>(this.targetMap.size());
|
||||
for (Entry<K, List<V>> entry : targetMap.entrySet()) {
|
||||
singleValueMap.put(entry.getKey(), entry.getValue().get(0));
|
||||
}
|
||||
return singleValueMap;
|
||||
}
|
||||
|
||||
// Map implementation
|
||||
|
||||
|
|
|
|||
|
|
@ -48,4 +48,16 @@ public interface MultiValueMap<K, V> extends Map<K, List<V>> {
|
|||
*/
|
||||
void set(K key, V value);
|
||||
|
||||
/**
|
||||
* Set the given values under.
|
||||
* @param values the values.
|
||||
*/
|
||||
void setAll(Map<K, V> values);
|
||||
|
||||
/**
|
||||
* Returns the first values contained in this {@code MultiValueMap}.
|
||||
* @return a single value representation of this map
|
||||
*/
|
||||
Map<K, V> toSingleValueMap();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,11 @@ import java.util.Collections;
|
|||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
||||
|
|
@ -35,12 +38,13 @@ import org.springframework.web.multipart.MultipartHttpServletRequest;
|
|||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Eric Crampton
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
* @see MockMultipartFile
|
||||
*/
|
||||
public class MockMultipartHttpServletRequest extends MockHttpServletRequest implements MultipartHttpServletRequest {
|
||||
|
||||
private final Map<String, MultipartFile> multipartFiles = new LinkedHashMap<String, MultipartFile>();
|
||||
private final MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<String, MultipartFile>();
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -50,7 +54,7 @@ public class MockMultipartHttpServletRequest extends MockHttpServletRequest impl
|
|||
*/
|
||||
public void addFile(MultipartFile file) {
|
||||
Assert.notNull(file, "MultipartFile must not be null");
|
||||
this.multipartFiles.put(file.getName(), file);
|
||||
this.multipartFiles.add(file.getName(), file);
|
||||
}
|
||||
|
||||
public Iterator<String> getFileNames() {
|
||||
|
|
@ -58,11 +62,25 @@ public class MockMultipartHttpServletRequest extends MockHttpServletRequest impl
|
|||
}
|
||||
|
||||
public MultipartFile getFile(String name) {
|
||||
return this.multipartFiles.get(name);
|
||||
return this.multipartFiles.getFirst(name);
|
||||
}
|
||||
|
||||
public List<MultipartFile> getFiles(String name) {
|
||||
List<MultipartFile> multipartFiles = this.multipartFiles.get(name);
|
||||
if (multipartFiles != null) {
|
||||
return multipartFiles;
|
||||
}
|
||||
else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, MultipartFile> getFileMap() {
|
||||
return Collections.unmodifiableMap(this.multipartFiles);
|
||||
return Collections.unmodifiableMap(this.multipartFiles.toSingleValueMap());
|
||||
}
|
||||
|
||||
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
|
||||
return new LinkedMultiValueMap<String, MultipartFile>(Collections.unmodifiableMap(this.multipartFiles));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,11 @@ import java.util.Collections;
|
|||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.portlet.multipart.MultipartActionRequest;
|
||||
|
||||
|
|
@ -34,12 +37,13 @@ import org.springframework.web.portlet.multipart.MultipartActionRequest;
|
|||
* populate these mock requests with files.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
* @see org.springframework.mock.web.MockMultipartFile
|
||||
*/
|
||||
public class MockMultipartActionRequest extends MockActionRequest implements MultipartActionRequest {
|
||||
|
||||
private final Map<String, MultipartFile> multipartFiles = new LinkedHashMap<String, MultipartFile>();
|
||||
private final MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<String, MultipartFile>();
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -49,7 +53,7 @@ public class MockMultipartActionRequest extends MockActionRequest implements Mul
|
|||
*/
|
||||
public void addFile(MultipartFile file) {
|
||||
Assert.notNull(file, "MultipartFile must not be null");
|
||||
this.multipartFiles.put(file.getName(), file);
|
||||
this.multipartFiles.add(file.getName(), file);
|
||||
}
|
||||
|
||||
public Iterator<String> getFileNames() {
|
||||
|
|
@ -57,11 +61,25 @@ public class MockMultipartActionRequest extends MockActionRequest implements Mul
|
|||
}
|
||||
|
||||
public MultipartFile getFile(String name) {
|
||||
return this.multipartFiles.get(name);
|
||||
return this.multipartFiles.getFirst(name);
|
||||
}
|
||||
|
||||
public List<MultipartFile> getFiles(String name) {
|
||||
List<MultipartFile> multipartFiles = this.multipartFiles.get(name);
|
||||
if (multipartFiles != null) {
|
||||
return multipartFiles;
|
||||
}
|
||||
else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, MultipartFile> getFileMap() {
|
||||
return Collections.unmodifiableMap(this.multipartFiles);
|
||||
return Collections.unmodifiableMap(this.multipartFiles.toSingleValueMap());
|
||||
}
|
||||
|
||||
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
|
||||
return new LinkedMultiValueMap<String, MultipartFile>(Collections.unmodifiableMap(this.multipartFiles));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,22 +23,26 @@ import java.util.HashSet;
|
|||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.List;
|
||||
import javax.portlet.ActionRequest;
|
||||
import javax.portlet.filter.ActionRequestWrapper;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
|
||||
/**
|
||||
* Default implementation of the {@link MultipartActionRequest} interface.
|
||||
* Provides management of pre-generated parameter values.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
* @see PortletMultipartResolver
|
||||
*/
|
||||
public class DefaultMultipartActionRequest extends ActionRequestWrapper implements MultipartActionRequest {
|
||||
|
||||
private Map<String, MultipartFile> multipartFiles;
|
||||
private MultiValueMap<String, MultipartFile> multipartFiles;
|
||||
|
||||
private Map<String, String[]> multipartParameters;
|
||||
|
||||
|
|
@ -51,7 +55,7 @@ public class DefaultMultipartActionRequest extends ActionRequestWrapper implemen
|
|||
* with Strings as keys and String arrays as values
|
||||
*/
|
||||
public DefaultMultipartActionRequest(
|
||||
ActionRequest request, Map<String, MultipartFile> mpFiles, Map<String, String[]> mpParams) {
|
||||
ActionRequest request, MultiValueMap<String, MultipartFile> mpFiles, Map<String, String[]> mpParams) {
|
||||
|
||||
super(request);
|
||||
setMultipartFiles(mpFiles);
|
||||
|
|
@ -72,13 +76,27 @@ public class DefaultMultipartActionRequest extends ActionRequestWrapper implemen
|
|||
}
|
||||
|
||||
public MultipartFile getFile(String name) {
|
||||
return getMultipartFiles().get(name);
|
||||
return getMultipartFiles().getFirst(name);
|
||||
}
|
||||
|
||||
public List<MultipartFile> getFiles(String name) {
|
||||
List<MultipartFile> multipartFiles = getMultipartFiles().get(name);
|
||||
if (multipartFiles != null) {
|
||||
return multipartFiles;
|
||||
}
|
||||
else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Map<String, MultipartFile> getFileMap() {
|
||||
return getMultipartFiles();
|
||||
return getMultipartFiles().toSingleValueMap();
|
||||
}
|
||||
|
||||
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
|
||||
return getMultipartFiles();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Enumeration<String> getParameterNames() {
|
||||
|
|
@ -120,11 +138,12 @@ public class DefaultMultipartActionRequest extends ActionRequestWrapper implemen
|
|||
|
||||
|
||||
/**
|
||||
* Set a Map with parameter names as keys and MultipartFile objects as values.
|
||||
* Set a Map with parameter names as keys and list of MultipartFile objects as values.
|
||||
* To be invoked by subclasses on initialization.
|
||||
*/
|
||||
protected final void setMultipartFiles(Map<String, MultipartFile> multipartFiles) {
|
||||
this.multipartFiles = Collections.unmodifiableMap(multipartFiles);
|
||||
protected final void setMultipartFiles(MultiValueMap<String, MultipartFile> multipartFiles) {
|
||||
this.multipartFiles =
|
||||
new LinkedMultiValueMap<String, MultipartFile>(Collections.unmodifiableMap(multipartFiles));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -132,7 +151,7 @@ public class DefaultMultipartActionRequest extends ActionRequestWrapper implemen
|
|||
* lazily initializing it if necessary.
|
||||
* @see #initializeMultipart()
|
||||
*/
|
||||
protected Map<String, MultipartFile> getMultipartFiles() {
|
||||
protected MultiValueMap<String, MultipartFile> getMultipartFiles() {
|
||||
if (this.multipartFiles == null) {
|
||||
initializeMultipart();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,8 +20,11 @@ import java.util.Collections;
|
|||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.portlet.multipart.MultipartActionRequest;
|
||||
|
||||
|
|
@ -34,12 +37,13 @@ import org.springframework.web.portlet.multipart.MultipartActionRequest;
|
|||
* populate these mock requests with files.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
* @see org.springframework.mock.web.MockMultipartFile
|
||||
*/
|
||||
public class MockMultipartActionRequest extends MockActionRequest implements MultipartActionRequest {
|
||||
|
||||
private final Map<String, MultipartFile> multipartFiles = new LinkedHashMap<String, MultipartFile>();
|
||||
private final MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<String, MultipartFile>();
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -49,7 +53,7 @@ public class MockMultipartActionRequest extends MockActionRequest implements Mul
|
|||
*/
|
||||
public void addFile(MultipartFile file) {
|
||||
Assert.notNull(file, "MultipartFile must not be null");
|
||||
this.multipartFiles.put(file.getName(), file);
|
||||
this.multipartFiles.add(file.getName(), file);
|
||||
}
|
||||
|
||||
public Iterator<String> getFileNames() {
|
||||
|
|
@ -57,11 +61,24 @@ public class MockMultipartActionRequest extends MockActionRequest implements Mul
|
|||
}
|
||||
|
||||
public MultipartFile getFile(String name) {
|
||||
return this.multipartFiles.get(name);
|
||||
return this.multipartFiles.getFirst(name);
|
||||
}
|
||||
|
||||
public List<MultipartFile> getFiles(String name) {
|
||||
List<MultipartFile> multipartFiles = this.multipartFiles.get(name);
|
||||
if (multipartFiles != null) {
|
||||
return multipartFiles;
|
||||
}
|
||||
else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, MultipartFile> getFileMap() {
|
||||
return Collections.unmodifiableMap(this.multipartFiles);
|
||||
return Collections.unmodifiableMap(this.multipartFiles.toSingleValueMap());
|
||||
}
|
||||
|
||||
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
|
||||
return new LinkedMultiValueMap<String, MultipartFile>(Collections.unmodifiableMap(this.multipartFiles));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,10 +67,13 @@ import org.springframework.web.portlet.multipart.MultipartActionRequest;
|
|||
import org.springframework.web.portlet.multipart.PortletMultipartResolver;
|
||||
import org.springframework.web.portlet.mvc.Controller;
|
||||
import org.springframework.web.portlet.mvc.SimpleControllerHandlerAdapter;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Mark Fisher
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class ComplexPortletApplicationContext extends StaticPortletApplicationContext {
|
||||
|
||||
|
|
@ -472,8 +475,8 @@ public class ComplexPortletApplicationContext extends StaticPortletApplicationCo
|
|||
throw new IllegalStateException("Already resolved");
|
||||
}
|
||||
request.setAttribute("resolved", Boolean.TRUE);
|
||||
Map files = new HashMap();
|
||||
files.put("someFile", "someFile");
|
||||
MultiValueMap files = new LinkedMultiValueMap();
|
||||
files.set("someFile", "someFile");
|
||||
Map params = new HashMap();
|
||||
params.put("someParam", "someParam");
|
||||
return new DefaultMultipartActionRequest(request, files, params);
|
||||
|
|
|
|||
|
|
@ -20,8 +20,11 @@ import java.util.Collections;
|
|||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
|
||||
|
|
@ -35,12 +38,13 @@ import org.springframework.web.multipart.MultipartHttpServletRequest;
|
|||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Eric Crampton
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.0
|
||||
* @see MockMultipartFile
|
||||
*/
|
||||
public class MockMultipartHttpServletRequest extends MockHttpServletRequest implements MultipartHttpServletRequest {
|
||||
|
||||
private final Map<String, MultipartFile> multipartFiles = new LinkedHashMap<String, MultipartFile>();
|
||||
private final MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<String, MultipartFile>();
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -50,7 +54,7 @@ public class MockMultipartHttpServletRequest extends MockHttpServletRequest impl
|
|||
*/
|
||||
public void addFile(MultipartFile file) {
|
||||
Assert.notNull(file, "MultipartFile must not be null");
|
||||
this.multipartFiles.put(file.getName(), file);
|
||||
this.multipartFiles.add(file.getName(), file);
|
||||
}
|
||||
|
||||
public Iterator<String> getFileNames() {
|
||||
|
|
@ -58,11 +62,24 @@ public class MockMultipartHttpServletRequest extends MockHttpServletRequest impl
|
|||
}
|
||||
|
||||
public MultipartFile getFile(String name) {
|
||||
return this.multipartFiles.get(name);
|
||||
return this.multipartFiles.getFirst(name);
|
||||
}
|
||||
|
||||
public List<MultipartFile> getFiles(String name) {
|
||||
List<MultipartFile> multipartFiles = this.multipartFiles.get(name);
|
||||
if (multipartFiles != null) {
|
||||
return multipartFiles;
|
||||
}
|
||||
else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, MultipartFile> getFileMap() {
|
||||
return Collections.unmodifiableMap(this.multipartFiles);
|
||||
return Collections.unmodifiableMap(this.multipartFiles.toSingleValueMap());
|
||||
}
|
||||
|
||||
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
|
||||
return new LinkedMultiValueMap<String, MultipartFile>(Collections.unmodifiableMap(this.multipartFiles));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ import java.util.Locale;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.LinkedCaseInsensitiveMap;
|
||||
|
|
@ -494,6 +495,19 @@ public class HttpHeaders implements MultiValueMap<String, String> {
|
|||
headers.put(headerName, headerValues);
|
||||
}
|
||||
|
||||
public void setAll(Map<String, String> values) {
|
||||
for (Entry<String, String> entry : values.entrySet()) {
|
||||
set(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, String> toSingleValueMap() {
|
||||
LinkedHashMap<String, String> singleValueMap = new LinkedHashMap<String,String>(this.headers.size());
|
||||
for (Entry<String, List<String>> entry : headers.entrySet()) {
|
||||
singleValueMap.put(entry.getKey(), entry.getValue().get(0));
|
||||
}
|
||||
return singleValueMap;
|
||||
}
|
||||
|
||||
// Map implementation
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@ package org.springframework.web.multipart;
|
|||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* This interface defines the multipart request access operations
|
||||
|
|
@ -26,6 +29,7 @@ import java.util.Map;
|
|||
* {@link org.springframework.web.portlet.multipart.MultipartActionRequest}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
* @since 2.5.2
|
||||
*/
|
||||
public interface MultipartRequest {
|
||||
|
|
@ -43,16 +47,33 @@ public interface MultipartRequest {
|
|||
* Return the contents plus description of an uploaded file in this request,
|
||||
* or <code>null</code> if it does not exist.
|
||||
* @param name a String specifying the parameter name of the multipart file
|
||||
* @return the uploaded content in the form of a {@link org.springframework.web.multipart.MultipartFile} object
|
||||
* @return the uploaded content in the form of a {@link MultipartFile} object
|
||||
*/
|
||||
MultipartFile getFile(String name);
|
||||
|
||||
/**
|
||||
* Return the contents plus description of uploaded files in this request,
|
||||
* or an empty list if it does not exist.
|
||||
* @param name a String specifying the parameter name of the multipart file
|
||||
* @return the uploaded content in the form of a {@link MultipartFile} list
|
||||
*/
|
||||
List<MultipartFile> getFiles(String name);
|
||||
|
||||
/**
|
||||
* Return a {@link java.util.Map} of the multipart files contained in this request.
|
||||
* @return a map containing the parameter names as keys, and the
|
||||
* {@link org.springframework.web.multipart.MultipartFile} objects as values
|
||||
* {@link MultipartFile} objects as values
|
||||
* @see MultipartFile
|
||||
*/
|
||||
Map<String, MultipartFile> getFileMap();
|
||||
|
||||
/**
|
||||
* Return a {@link MultiValueMap} of the multipart files contained in this request.
|
||||
* @return a map containing the parameter names as keys, and a list of
|
||||
* {@link MultipartFile} objects as values
|
||||
* @see MultipartFile
|
||||
*/
|
||||
MultiValueMap<String, MultipartFile> getMultiFileMap();
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,8 +31,9 @@ import org.apache.commons.logging.Log;
|
|||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.multipart.MultipartException;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
|
|
@ -213,7 +214,7 @@ public abstract class CommonsFileUploadSupport {
|
|||
* @see CommonsMultipartFile#CommonsMultipartFile(org.apache.commons.fileupload.FileItem)
|
||||
*/
|
||||
protected MultipartParsingResult parseFileItems(List<FileItem> fileItems, String encoding) {
|
||||
Map<String, MultipartFile> multipartFiles = new HashMap<String, MultipartFile>();
|
||||
MultiValueMap<String, MultipartFile> multipartFiles = new LinkedMultiValueMap<String, MultipartFile>();
|
||||
Map<String, String[]> multipartParameters = new HashMap<String, String[]>();
|
||||
|
||||
// Extract multipart files and multipart parameters.
|
||||
|
|
@ -249,10 +250,7 @@ public abstract class CommonsFileUploadSupport {
|
|||
else {
|
||||
// multipart file field
|
||||
CommonsMultipartFile file = new CommonsMultipartFile(fileItem);
|
||||
if (multipartFiles.put(file.getName(), file) != null) {
|
||||
throw new MultipartException("Multiple files for field name [" + file.getName() +
|
||||
"] found - not supported by MultipartResolver");
|
||||
}
|
||||
multipartFiles.add(file.getName(), file);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Found multipart file [" + file.getName() + "] of size " + file.getSize() +
|
||||
" bytes with original filename [" + file.getOriginalFilename() + "], stored " +
|
||||
|
|
@ -290,7 +288,7 @@ public abstract class CommonsFileUploadSupport {
|
|||
*/
|
||||
protected static class MultipartParsingResult {
|
||||
|
||||
private final Map<String, MultipartFile> multipartFiles;
|
||||
private final MultiValueMap<String, MultipartFile> multipartFiles;
|
||||
|
||||
private final Map<String, String[]> multipartParameters;
|
||||
|
||||
|
|
@ -299,7 +297,7 @@ public abstract class CommonsFileUploadSupport {
|
|||
* @param mpFiles Map of field name to MultipartFile instance
|
||||
* @param mpParams Map of field name to form field String value
|
||||
*/
|
||||
public MultipartParsingResult(Map<String, MultipartFile> mpFiles, Map<String, String[]> mpParams) {
|
||||
public MultipartParsingResult(MultiValueMap<String, MultipartFile> mpFiles, Map<String, String[]> mpParams) {
|
||||
this.multipartFiles = mpFiles;
|
||||
this.multipartParameters = mpParams;
|
||||
}
|
||||
|
|
@ -307,7 +305,7 @@ public abstract class CommonsFileUploadSupport {
|
|||
/**
|
||||
* Return the multipart files as Map of field name to MultipartFile instance.
|
||||
*/
|
||||
public Map<String, MultipartFile> getMultipartFiles() {
|
||||
public MultiValueMap<String, MultipartFile> getMultipartFiles() {
|
||||
return this.multipartFiles;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,24 +19,28 @@ package org.springframework.web.multipart.support;
|
|||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.web.multipart.MultipartHttpServletRequest;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
|
||||
/**
|
||||
* Abstract base implementation of the MultipartHttpServletRequest interface.
|
||||
* Provides management of pre-generated MultipartFile instances.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
* @since 06.10.2003
|
||||
*/
|
||||
public abstract class AbstractMultipartHttpServletRequest extends HttpServletRequestWrapper
|
||||
implements MultipartHttpServletRequest {
|
||||
|
||||
private Map<String, MultipartFile> multipartFiles;
|
||||
private MultiValueMap<String, MultipartFile> multipartFiles;
|
||||
|
||||
|
||||
/**
|
||||
|
|
@ -53,20 +57,34 @@ public abstract class AbstractMultipartHttpServletRequest extends HttpServletReq
|
|||
}
|
||||
|
||||
public MultipartFile getFile(String name) {
|
||||
return getMultipartFiles().get(name);
|
||||
return getMultipartFiles().getFirst(name);
|
||||
}
|
||||
|
||||
public List<MultipartFile> getFiles(String name) {
|
||||
List<MultipartFile> multipartFiles = getMultipartFiles().get(name);
|
||||
if (multipartFiles != null) {
|
||||
return multipartFiles;
|
||||
}
|
||||
else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, MultipartFile> getFileMap() {
|
||||
return getMultipartFiles().toSingleValueMap();
|
||||
}
|
||||
|
||||
public MultiValueMap<String, MultipartFile> getMultiFileMap() {
|
||||
return getMultipartFiles();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set a Map with parameter names as keys and MultipartFile objects as values.
|
||||
* Set a Map with parameter names as keys and list of MultipartFile objects as values.
|
||||
* To be invoked by subclasses on initialization.
|
||||
*/
|
||||
protected final void setMultipartFiles(Map<String, MultipartFile> multipartFiles) {
|
||||
this.multipartFiles = Collections.unmodifiableMap(multipartFiles);
|
||||
protected final void setMultipartFiles(MultiValueMap<String, MultipartFile> multipartFiles) {
|
||||
this.multipartFiles =
|
||||
new LinkedMultiValueMap<String, MultipartFile>(Collections.unmodifiableMap(multipartFiles));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -74,7 +92,7 @@ public abstract class AbstractMultipartHttpServletRequest extends HttpServletReq
|
|||
* lazily initializing it if necessary.
|
||||
* @see #initializeMultipart()
|
||||
*/
|
||||
protected Map<String, MultipartFile> getMultipartFiles() {
|
||||
protected MultiValueMap<String, MultipartFile> getMultipartFiles() {
|
||||
if (this.multipartFiles == null) {
|
||||
initializeMultipart();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import java.util.Set;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* Default implementation of the
|
||||
|
|
@ -33,6 +34,7 @@ import org.springframework.web.multipart.MultipartFile;
|
|||
*
|
||||
* @author Trevor D. Cook
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
* @since 29.09.2003
|
||||
* @see org.springframework.web.multipart.MultipartResolver
|
||||
*/
|
||||
|
|
@ -49,7 +51,7 @@ public class DefaultMultipartHttpServletRequest extends AbstractMultipartHttpSer
|
|||
* with Strings as keys and String arrays as values
|
||||
*/
|
||||
public DefaultMultipartHttpServletRequest(
|
||||
HttpServletRequest request, Map<String, MultipartFile> mpFiles, Map<String, String[]> mpParams) {
|
||||
HttpServletRequest request, MultiValueMap<String, MultipartFile> mpFiles, Map<String, String[]> mpParams) {
|
||||
|
||||
super(request);
|
||||
setMultipartFiles(mpFiles);
|
||||
|
|
|
|||
|
|
@ -30,7 +30,6 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
|
|
@ -38,12 +37,13 @@ import javax.servlet.ServletResponse;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.commons.fileupload.FileItem;
|
||||
import org.apache.commons.fileupload.FileItemFactory;
|
||||
import org.apache.commons.fileupload.FileUpload;
|
||||
import org.apache.commons.fileupload.servlet.ServletFileUpload;
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.mock.web.MockFilterConfig;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
|
@ -59,18 +59,22 @@ import org.springframework.web.multipart.support.ByteArrayMultipartFileEditor;
|
|||
import org.springframework.web.multipart.support.MultipartFilter;
|
||||
import org.springframework.web.multipart.support.StringMultipartFileEditor;
|
||||
import org.springframework.web.util.WebUtils;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Arjen Poutsma
|
||||
* @since 08.10.2003
|
||||
*/
|
||||
public class CommonsMultipartResolverTests extends TestCase {
|
||||
public class CommonsMultipartResolverTests {
|
||||
|
||||
public void testWithApplicationContext() throws Exception {
|
||||
@Test
|
||||
public void withApplicationContext() throws Exception {
|
||||
doTestWithApplicationContext(false);
|
||||
}
|
||||
|
||||
public void testWithApplicationContextAndLazyResolution() throws Exception {
|
||||
@Test
|
||||
public void withApplicationContextAndLazyResolution() throws Exception {
|
||||
doTestWithApplicationContext(true);
|
||||
}
|
||||
|
||||
|
|
@ -100,10 +104,18 @@ public class CommonsMultipartResolverTests extends TestCase {
|
|||
assertTrue(resolver.isMultipart(originalRequest));
|
||||
MultipartHttpServletRequest request = resolver.resolveMultipart(originalRequest);
|
||||
|
||||
Set parameterNames = new HashSet();
|
||||
doTestParameters(request);
|
||||
|
||||
doTestFiles(request);
|
||||
|
||||
doTestBinding(resolver, originalRequest, request);
|
||||
}
|
||||
|
||||
private void doTestParameters(MultipartHttpServletRequest request) {
|
||||
Set<String> parameterNames = new HashSet<String>();
|
||||
Enumeration parameterEnum = request.getParameterNames();
|
||||
while (parameterEnum.hasMoreElements()) {
|
||||
parameterNames.add(parameterEnum.nextElement());
|
||||
parameterNames.add((String) parameterEnum.nextElement());
|
||||
}
|
||||
assertEquals(3, parameterNames.size());
|
||||
assertTrue(parameterNames.contains("field3"));
|
||||
|
|
@ -121,10 +133,10 @@ public class CommonsMultipartResolverTests extends TestCase {
|
|||
assertEquals("value4", request.getParameter("field4"));
|
||||
assertEquals("getValue", request.getParameter("getField"));
|
||||
|
||||
List parameterMapKeys = new ArrayList();
|
||||
List parameterMapValues = new ArrayList();
|
||||
for (Iterator parameterMapIter = request.getParameterMap().keySet().iterator(); parameterMapIter.hasNext();) {
|
||||
String key = (String) parameterMapIter.next();
|
||||
List<String> parameterMapKeys = new ArrayList<String>();
|
||||
List<Object> parameterMapValues = new ArrayList<Object>();
|
||||
for (Object o : request.getParameterMap().keySet()) {
|
||||
String key = (String) o;
|
||||
parameterMapKeys.add(key);
|
||||
parameterMapValues.add(request.getParameterMap().get(key));
|
||||
}
|
||||
|
|
@ -146,11 +158,13 @@ public class CommonsMultipartResolverTests extends TestCase {
|
|||
parameterValues = Arrays.asList((String[]) parameterMapValues.get(getFieldIndex));
|
||||
assertEquals(1, parameterValues.size());
|
||||
assertTrue(parameterValues.contains("getValue"));
|
||||
}
|
||||
|
||||
Set fileNames = new HashSet();
|
||||
private void doTestFiles(MultipartHttpServletRequest request) throws IOException {
|
||||
Set<String> fileNames = new HashSet<String>();
|
||||
Iterator fileIter = request.getFileNames();
|
||||
while (fileIter.hasNext()) {
|
||||
fileNames.add(fileIter.next());
|
||||
fileNames.add((String) fileIter.next());
|
||||
}
|
||||
assertEquals(3, fileNames.size());
|
||||
assertTrue(fileNames.contains("field1"));
|
||||
|
|
@ -159,7 +173,8 @@ public class CommonsMultipartResolverTests extends TestCase {
|
|||
CommonsMultipartFile file1 = (CommonsMultipartFile) request.getFile("field1");
|
||||
CommonsMultipartFile file2 = (CommonsMultipartFile) request.getFile("field2");
|
||||
CommonsMultipartFile file2x = (CommonsMultipartFile) request.getFile("field2x");
|
||||
Map fileMap = request.getFileMap();
|
||||
|
||||
Map<String, MultipartFile> fileMap = request.getFileMap();
|
||||
assertEquals(3, fileMap.size());
|
||||
assertTrue(fileMap.containsKey("field1"));
|
||||
assertTrue(fileMap.containsKey("field2"));
|
||||
|
|
@ -168,6 +183,18 @@ public class CommonsMultipartResolverTests extends TestCase {
|
|||
assertEquals(file2, fileMap.get("field2"));
|
||||
assertEquals(file2x, fileMap.get("field2x"));
|
||||
|
||||
MultiValueMap<String, MultipartFile> multiFileMap = request.getMultiFileMap();
|
||||
assertEquals(3, multiFileMap.size());
|
||||
assertTrue(multiFileMap.containsKey("field1"));
|
||||
assertTrue(multiFileMap.containsKey("field2"));
|
||||
assertTrue(multiFileMap.containsKey("field2x"));
|
||||
List<MultipartFile> field1Files = multiFileMap.get("field1");
|
||||
assertEquals(2, field1Files.size());
|
||||
assertTrue(field1Files.contains(file1));
|
||||
assertEquals(file1, multiFileMap.getFirst("field1"));
|
||||
assertEquals(file2, multiFileMap.getFirst("field2"));
|
||||
assertEquals(file2x, multiFileMap.getFirst("field2x"));
|
||||
|
||||
assertEquals("type1", file1.getContentType());
|
||||
assertEquals("type2", file2.getContentType());
|
||||
assertEquals("type2", file2x.getContentType());
|
||||
|
|
@ -181,18 +208,24 @@ public class CommonsMultipartResolverTests extends TestCase {
|
|||
assertTrue(file1.getInputStream() instanceof ByteArrayInputStream);
|
||||
assertTrue(file2.getInputStream() instanceof ByteArrayInputStream);
|
||||
File transfer1 = new File("C:/transfer1");
|
||||
File transfer2 = new File("C:/transfer2");
|
||||
file1.transferTo(transfer1);
|
||||
File transfer2 = new File("C:/transfer2");
|
||||
file2.transferTo(transfer2);
|
||||
assertEquals(transfer1, ((MockFileItem) file1.getFileItem()).writtenFile);
|
||||
assertEquals(transfer2, ((MockFileItem) file2.getFileItem()).writtenFile);
|
||||
|
||||
}
|
||||
|
||||
private void doTestBinding(MockCommonsMultipartResolver resolver, MockHttpServletRequest originalRequest,
|
||||
MultipartHttpServletRequest request) throws UnsupportedEncodingException {
|
||||
MultipartTestBean1 mtb1 = new MultipartTestBean1();
|
||||
assertEquals(null, mtb1.getField1());
|
||||
assertEquals(null, mtb1.getField2());
|
||||
ServletRequestDataBinder binder = new ServletRequestDataBinder(mtb1, "mybean");
|
||||
binder.registerCustomEditor(byte[].class, new ByteArrayMultipartFileEditor());
|
||||
binder.bind(request);
|
||||
CommonsMultipartFile file1 = (CommonsMultipartFile) request.getFile("field1");
|
||||
CommonsMultipartFile file2 = (CommonsMultipartFile) request.getFile("field2");
|
||||
assertEquals(file1, mtb1.getField1());
|
||||
assertEquals(new String(file2.getBytes()), new String(mtb1.getField2()));
|
||||
|
||||
|
|
@ -224,7 +257,8 @@ public class CommonsMultipartResolverTests extends TestCase {
|
|||
assertTrue(mtb2.getField1().length() == 0);
|
||||
}
|
||||
|
||||
public void testWithServletContextAndFilter() throws Exception {
|
||||
@Test
|
||||
public void withServletContextAndFilter() throws Exception {
|
||||
StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||
wac.setServletContext(new MockServletContext());
|
||||
wac.registerSingleton("filterMultipartResolver", MockCommonsMultipartResolver.class, new MutablePropertyValues());
|
||||
|
|
@ -240,7 +274,7 @@ public class CommonsMultipartResolverTests extends TestCase {
|
|||
final MultipartFilter filter = new MultipartFilter();
|
||||
filter.init(filterConfig);
|
||||
|
||||
final List files = new ArrayList();
|
||||
final List<MultipartFile> files = new ArrayList<MultipartFile>();
|
||||
final FilterChain filterChain = new FilterChain() {
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse) {
|
||||
MultipartHttpServletRequest request = (MultipartHttpServletRequest) servletRequest;
|
||||
|
|
@ -263,7 +297,8 @@ public class CommonsMultipartResolverTests extends TestCase {
|
|||
assertTrue(((MockFileItem) file2.getFileItem()).deleted);
|
||||
}
|
||||
|
||||
public void testWithServletContextAndFilterWithCustomBeanName() throws Exception {
|
||||
@Test
|
||||
public void withServletContextAndFilterWithCustomBeanName() throws Exception {
|
||||
StaticWebApplicationContext wac = new StaticWebApplicationContext();
|
||||
wac.setServletContext(new MockServletContext());
|
||||
wac.refresh();
|
||||
|
|
@ -276,7 +311,7 @@ public class CommonsMultipartResolverTests extends TestCase {
|
|||
MockFilterConfig filterConfig = new MockFilterConfig(wac.getServletContext(), "filter");
|
||||
filterConfig.addInitParameter("multipartResolverBeanName", "myMultipartResolver");
|
||||
|
||||
final List files = new ArrayList();
|
||||
final List<MultipartFile> files = new ArrayList<MultipartFile>();
|
||||
FilterChain filterChain = new FilterChain() {
|
||||
public void doFilter(ServletRequest originalRequest, ServletResponse response) {
|
||||
if (originalRequest instanceof MultipartHttpServletRequest) {
|
||||
|
|
@ -288,6 +323,7 @@ public class CommonsMultipartResolverTests extends TestCase {
|
|||
|
||||
MultipartFilter filter = new MultipartFilter() {
|
||||
private boolean invoked = false;
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
|
||||
FilterChain filterChain) throws ServletException, IOException {
|
||||
super.doFilterInternal(request, response, filterChain);
|
||||
|
|
@ -321,15 +357,19 @@ public class CommonsMultipartResolverTests extends TestCase {
|
|||
this.empty = empty;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected FileUpload newFileUpload(FileItemFactory fileItemFactory) {
|
||||
return new ServletFileUpload() {
|
||||
@Override
|
||||
public List parseRequest(HttpServletRequest request) {
|
||||
if (request instanceof MultipartHttpServletRequest) {
|
||||
throw new IllegalStateException("Already a multipart request");
|
||||
}
|
||||
List fileItems = new ArrayList();
|
||||
List<FileItem> fileItems = new ArrayList<FileItem>();
|
||||
MockFileItem fileItem1 = new MockFileItem(
|
||||
"field1", "type1", empty ? "" : "field1.txt", empty ? "" : "text1");
|
||||
MockFileItem fileItem1x = new MockFileItem(
|
||||
"field1", "type1", empty ? "" : "field1.txt", empty ? "" : "text1");
|
||||
MockFileItem fileItem2 = new MockFileItem(
|
||||
"field2", "type2", empty ? "" : "C:/field2.txt", empty ? "" : "text2");
|
||||
MockFileItem fileItem2x = new MockFileItem(
|
||||
|
|
@ -338,6 +378,7 @@ public class CommonsMultipartResolverTests extends TestCase {
|
|||
MockFileItem fileItem4 = new MockFileItem("field4", null, null, "value4");
|
||||
MockFileItem fileItem5 = new MockFileItem("field4", null, null, "value5");
|
||||
fileItems.add(fileItem1);
|
||||
fileItems.add(fileItem1x);
|
||||
fileItems.add(fileItem2);
|
||||
fileItems.add(fileItem2x);
|
||||
fileItems.add(fileItem3);
|
||||
|
|
|
|||
Loading…
Reference in New Issue