Spring 2.5 多文件上传

项目中遇到一个问题:需要一个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支持的单文件上传,经测试并不会影响原来的单文件上传。

当然项目中的情况可能比本文中的情况复杂的多,大家可以给我留言。
 




原文地址:https://www.cnblogs.com/hmdrzql/p/3622751.html