项目中遇到一个问题:需要一个html5的上传控件来实现多文件上传,经测试在structs 2框架下测试通过,
但是在spring 2.5框架下仅仅单文件测试通过,多文件上传(就是给input加上了multiple属性)报出异常。
异常如下:
org.springframework.web.multipart.MultipartException: Multiple files for field name [files] found - not supported by MultipartResolver org.springframework.web.multipart.commons.CommonsFileUploadSupport.parseFileItems(CommonsFileUploadSupport.java:254) org.springframework.web.multipart.commons.CommonsMultipartResolver.parseRequest(CommonsMultipartResolver.java:166) org.springframework.web.multipart.commons.CommonsMultipartResolver.resolveMultipart(CommonsMultipartResolver.java:149) org.springframework.web.servlet.DispatcherServlet.checkMultipart(DispatcherServlet.java:1015) org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:851) org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:807) org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571) org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:511) javax.servlet.http.HttpServlet.service(HttpServlet.java:637) javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
说明控件本身没什么问题,一定是spring2.5的问题! google了一下,果然是spring2.5 陈年老bug!
见https://jira.spring.io/browse/SPR-2784
造成这样的异常的代码:
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");
}
解决方案有很多,这篇文章先介绍一种。由于CommonsMultipartResolver 不是final的,所以可以继承并改写他的逻辑。
package resolver;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import org.apache.commons.fileupload.FileItem;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartException;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
public class MultiCommonsMultipartResolver extends CommonsMultipartResolver {
public MultiCommonsMultipartResolver() {
}
public MultiCommonsMultipartResolver(ServletContext servletContext) {
super(servletContext);
}
@Override
@SuppressWarnings("unchecked")
protected MultipartParsingResult parseFileItems(List fileItems, String encoding) {
Map multipartFiles = new HashMap();
Map multipartParameters = new HashMap();
// Extract multipart files and multipart parameters.
for (Iterator it = fileItems.iterator(); it.hasNext();) {
FileItem fileItem = (FileItem) it.next();
if (fileItem.isFormField()) {
String value = null;
if (encoding != null) {
try {
value = fileItem.getString(encoding);
} catch (UnsupportedEncodingException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Could not decode multipart item '" + fileItem.getFieldName()
+ "' with encoding '" + encoding + "': using platform default");
}
value = fileItem.getString();
}
} else {
value = fileItem.getString();
}
String[] curParam = (String[]) multipartParameters.get(fileItem.getFieldName());
if (curParam == null) {
// simple form field
multipartParameters.put(fileItem.getFieldName(), new String[] { value });
} else {
// array of simple form fields
String[] newParam = StringUtils.addStringToArray(curParam, value);
multipartParameters.put(fileItem.getFieldName(), newParam);
}
} else {
// multipart file field
CommonsMultipartFile file = new CommonsMultipartFile(fileItem);
if (multipartFiles.put(fileItem.getName(), file) != null) {
throw new MultipartException("Multiple files for field name [" + file.getName()
+ "] found - not supported by MultipartResolver");
}
if (logger.isDebugEnabled()) {
logger.debug("Found multipart file [" + file.getName() + "] of size " + file.getSize()
+ " bytes with original filename [" + file.getOriginalFilename() + "], stored "
+ file.getStorageDescription());
}
}
}
return new MultipartParsingResult(multipartFiles, multipartParameters);
}
}
spring 配置改成你新写的这个类,默认是CommonsMultipartResolver
<bean id="multipartResolver" class="resolver.MultiCommonsMultipartResolver"> <property name="maxUploadSize" value="5000000" /> <property name="maxInMemorySize" value="5000000" /> </bean>
测试通过。这种解决方案还适用于spring2.5项目中已经做过用spring2.5支持的单文件上传,经测试并不会影响原来的单文件上传。
当然项目中的情况可能比本文中的情况复杂的多,大家可以给我留言。