diff --git a/spring-web/src/main/java/org/springframework/web/multipart/support/DefaultMultipartHttpServletRequest.java b/spring-web/src/main/java/org/springframework/web/multipart/support/DefaultMultipartHttpServletRequest.java index 86a8f79c4a..b1cea0cbb4 100644 --- a/spring-web/src/main/java/org/springframework/web/multipart/support/DefaultMultipartHttpServletRequest.java +++ b/spring-web/src/main/java/org/springframework/web/multipart/support/DefaultMultipartHttpServletRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 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. @@ -19,7 +19,7 @@ package org.springframework.web.multipart.support; import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; @@ -33,6 +33,8 @@ import org.springframework.web.multipart.MultipartFile; * {@link org.springframework.web.multipart.MultipartHttpServletRequest} * interface. Provides management of pre-generated parameter values. * + *

Used by {@link org.springframework.web.multipart.commons.CommonsMultipartResolver}. + * * @author Trevor D. Cook * @author Juergen Hoeller * @author Arjen Poutsma @@ -75,12 +77,17 @@ public class DefaultMultipartHttpServletRequest extends AbstractMultipartHttpSer @Override public Enumeration getParameterNames() { - Set paramNames = new HashSet(); + Map multipartParameters = getMultipartParameters(); + if (multipartParameters.isEmpty()) { + return super.getParameterNames(); + } + + Set paramNames = new LinkedHashSet(); Enumeration paramEnum = super.getParameterNames(); while (paramEnum.hasMoreElements()) { paramNames.add(paramEnum.nextElement()); } - paramNames.addAll(getMultipartParameters().keySet()); + paramNames.addAll(multipartParameters.keySet()); return Collections.enumeration(paramNames); } diff --git a/spring-web/src/main/java/org/springframework/web/multipart/support/StandardMultipartHttpServletRequest.java b/spring-web/src/main/java/org/springframework/web/multipart/support/StandardMultipartHttpServletRequest.java index 46a9886fe2..90cb3d6386 100644 --- a/spring-web/src/main/java/org/springframework/web/multipart/support/StandardMultipartHttpServletRequest.java +++ b/spring-web/src/main/java/org/springframework/web/multipart/support/StandardMultipartHttpServletRequest.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 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. @@ -21,6 +21,10 @@ import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.Enumeration; +import java.util.LinkedHashSet; +import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.Part; @@ -45,22 +49,47 @@ public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpSe private static final String FILENAME_KEY = "filename="; + private Set multipartParameterNames; + /** - * Create a new StandardMultipartHttpServletRequest wrapper for the given request. + * Create a new StandardMultipartHttpServletRequest wrapper for the given request, + * immediately parsing the multipart content. * @param request the servlet request to wrap * @throws MultipartException if parsing failed */ public StandardMultipartHttpServletRequest(HttpServletRequest request) throws MultipartException { + this(request, false); + } + + /** + * Create a new StandardMultipartHttpServletRequest wrapper for the given request. + * @param request the servlet request to wrap + * @param lazyParsing whether multipart parsing should be triggered lazily on + * first access of multipart files or parameters + * @throws MultipartException if an immediate parsing attempt failed + */ + public StandardMultipartHttpServletRequest(HttpServletRequest request, boolean lazyParsing) throws MultipartException { super(request); + if (!lazyParsing) { + parseRequest(request); + } + } + + + private void parseRequest(HttpServletRequest request) { try { Collection parts = request.getParts(); + this.multipartParameterNames = new LinkedHashSet(parts.size()); MultiValueMap files = new LinkedMultiValueMap(parts.size()); for (Part part : parts) { String filename = extractFilename(part.getHeader(CONTENT_DISPOSITION)); if (filename != null) { files.add(part.getName(), new StandardMultipartFile(part, filename)); } + else { + this.multipartParameterNames.add(part.getName()); + } } setMultipartFiles(files); } @@ -95,6 +124,29 @@ public class StandardMultipartHttpServletRequest extends AbstractMultipartHttpSe } + @Override + protected void initializeMultipart() { + parseRequest(getRequest()); + } + + @Override + public Enumeration getParameterNames() { + if (this.multipartParameterNames == null) { + initializeMultipart(); + } + if (this.multipartParameterNames.isEmpty()) { + return super.getParameterNames(); + } + + Set paramNames = new LinkedHashSet(); + Enumeration paramEnum = super.getParameterNames(); + while (paramEnum.hasMoreElements()) { + paramNames.add(paramEnum.nextElement()); + } + paramNames.addAll(this.multipartParameterNames); + return Collections.enumeration(paramNames); + } + @Override public String getMultipartContentType(String paramOrFileName) { try { diff --git a/spring-web/src/main/java/org/springframework/web/multipart/support/StandardServletMultipartResolver.java b/spring-web/src/main/java/org/springframework/web/multipart/support/StandardServletMultipartResolver.java index 25cc39510a..91269a65c4 100644 --- a/spring-web/src/main/java/org/springframework/web/multipart/support/StandardServletMultipartResolver.java +++ b/spring-web/src/main/java/org/springframework/web/multipart/support/StandardServletMultipartResolver.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2014 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. @@ -45,6 +45,22 @@ import org.springframework.web.multipart.MultipartResolver; */ public class StandardServletMultipartResolver implements MultipartResolver { + private boolean resolveLazily = false; + + + /** + * Set whether to resolve the multipart request lazily at the time of + * file or parameter access. + *

Default is "false", resolving the multipart elements immediately, throwing + * corresponding exceptions at the time of the {@link #resolveMultipart} call. + * Switch this to "true" for lazy multipart parsing, throwing parse exceptions + * once the application attempts to obtain multipart files or parameters. + */ + public void setResolveLazily(boolean resolveLazily) { + this.resolveLazily = resolveLazily; + } + + @Override public boolean isMultipart(HttpServletRequest request) { // Same check as in Commons FileUpload... @@ -57,7 +73,7 @@ public class StandardServletMultipartResolver implements MultipartResolver { @Override public MultipartHttpServletRequest resolveMultipart(HttpServletRequest request) throws MultipartException { - return new StandardMultipartHttpServletRequest(request); + return new StandardMultipartHttpServletRequest(request, this.resolveLazily); } @Override