项目中遇到一个问题:需要一个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支持的单文件上传,经测试并不会影响原来的单文件上传。
当然项目中的情况可能比本文中的情况复杂的多,大家可以给我留言。