重要提示: 对于早于 3.0.4的 任何Spring版本,此问题完全无用,因为该线程中讨论的问题早已在该版本中修复,并且在以后的Spring版本中不再可重现。
我正在使用Spring版本3.0.2。我需要使用multiple="multiple"文件浏览器的属性上传多个文件,例如,
multiple="multiple"
<input type="file" id="myFile" name="myFile" multiple="multiple"/>
尽管除非使用适当的jQuery插件/小部件,否则Internet Explorer的任何版本都不支持该方法,但是我现在不在乎(因为大多数其他浏览器都支持此方法)。
这正常工作与通用FileUpload但除了使用RequestMethod.POST和RequestMethod.GET方法,我也想用类似的支撑,并建议由Spring其他请求方法RequestMethod.PUT,并RequestMethod.DELETE在自己合适的位置。为此,我已经配置了Spring,HiddenHttpMethodFilter正如这个问题所表明的那样,它运行得很好。
RequestMethod.POST
RequestMethod.GET
RequestMethod.PUT
RequestMethod.DELETE
HiddenHttpMethodFilter
但即使在文件浏览器中选择了多个文件, 它一次也只能上传一个文件 。在Spring控制器类中,方法映射如下。
@RequestMapping(method={RequestMethod.POST}, value={"admin_side/Temp"}) public String onSubmit(@RequestParam("myFile") List<MultipartFile> files, @ModelAttribute("tempBean") TempBean tempBean, BindingResult error, Map model, HttpServletRequest request, HttpServletResponse response) throws IOException, FileUploadException { for (MultipartFile file : files) { System.out.println(file.getOriginalFilename()); } }
即使请求参数@RequestParam("myFile") List<MultipartFile> files是a List类型MultipartFile(每次始终只能有一个文件)。
@RequestParam("myFile") List<MultipartFile> files
List
MultipartFile
我可以在该博客上找到一种可能适用于多个文件的策略。我仔细地检查了一下。
解决 方案2 –使用原始请求 部分 下面 的 解决方案 说,
但是 , 如果 客户坚持使用相同的形式输入名称(例如“ files []”或“ files”),然后用多个文件填充该名称,则需要进行如下操作 。如上所述,如果Spring 2.5多次检测到相同类型的文件类型输入,则会引发异常。CommonsFileUploadSupport - 其抛出该异常的类不是最终和 方法,其抛出异常是受保护的,以便使用继承的奇迹和子类可以简单地修正/修改的逻辑一点点如下。我所做的更改实际上是一个词,代表一个方法调用,这使我们能够以相同的格式输入名称来传入多个文件。
它尝试覆盖该方法
protected MultipartParsingResult parseFileItems(List fileItems, String encoding){}
CommonsFileUploadSupport通过扩展CommonsMultipartResolver此类,例如抽象类
CommonsFileUploadSupport
CommonsMultipartResolver
package multipartResolver; 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.MultipartFile; import org.springframework.web.multipart.commons.CommonsMultipartFile; import org.springframework.web.multipart.commons.CommonsMultipartResolver; public final class MultiCommonsMultipartResolver extends CommonsMultipartResolver { public MultiCommonsMultipartResolver() {} public MultiCommonsMultipartResolver(ServletContext servletContext) { super(servletContext); } @Override @SuppressWarnings("unchecked") protected MultipartParsingResult parseFileItems(List fileItems, String encoding) { Map<String, MultipartFile> multipartFiles = new HashMap<String, MultipartFile>(); 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); } }
发生的是方法的最后一行parseFileItems()(return语句),即
parseFileItems()
return new MultipartParsingResult(multipartFiles, multipartParameters);
导致编译时错误,因为第一个参数multipartFiles是由Map实现的类型, 但实际上,它需要一个类型的参数*HashMap *MultiValueMap<String, MultipartFile>
multipartFiles
Map
HashMap
MultiValueMap<String, MultipartFile>
它是抽象类内部的静态类的构造函数CommonsFileUploadSupport,
public abstract class CommonsFileUploadSupport { protected static class MultipartParsingResult { public MultipartParsingResult(MultiValueMap<String, MultipartFile> mpFiles, Map<String, String[]> mpParams) {} } }
原因可能是-该解决方案是关于Spring 2.5版的,而我使用的是Spring 3.0.2版,可能不适用于该版本。
然而,我试图替换Map用MultiValueMap各种方式,例如在下面的代码段中所示的一个,
MultiValueMap
MultiValueMap<String, MultipartFile>mul=new LinkedMultiValueMap<String, MultipartFile>(); for(Entry<String, MultipartFile>entry:multipartFiles.entrySet()) { mul.add(entry.getKey(), entry.getValue()); } return new MultipartParsingResult(mul, multipartParameters);
但没有成功。我不确定如何将其替换Map,MultiValueMap甚至这样做也可以。完成此操作后,浏览器将显示Http响应,
HTTP状态400- 类型状态报告 信息 描述客户端发送的请求在语法上不正确()。 Apache Tomcat / 6.0.26
HTTP状态400-
类型状态报告
信息
描述客户端发送的请求在语法上不正确()。
Apache Tomcat / 6.0.26
我已经尝试过尽可能缩短问题的范围,并且没有包含不必要的代码。
在配置Spring之后,如何才能上传多个文件HiddenHttpMethodFilter?
该博客表明这是一个长期存在的高优先级错误。
如果没有关于版本3.0.2(3或更高版本)的解决方案,那么我必须永久禁用Spring支持,并继续按照该博客上第三个解决方案的建议继续使用commons- fileupolad,从而永远省略PUT,DELETE和其他请求方法。
parseFileItems()对类内部方法中的代码进行的很少更改MultiCommonsMultipartResolver 可能会使它上载多个文件,但我尝试失败(再次使用Spring 3.0.2(3或更高版本))。
MultiCommonsMultipartResolver
问题中提到的问题已在Spring 3.0.4中修复。因此,如果您恰巧使用该版本或更高版本(是的,现在是4.xx),则无需再阅读此问题。