Загрузка нескольких файлов с помощью Spring MVC 3.0.2 после включения HiddenHttpMethodFilter
важно : этот вопрос совершенно бесполезен для любой весенней версии выше 3.0.4 как обсуждаемый в этой теме было!--36-->основные в этой версии давно и больше не воспроизводится в последующих версиях Spring.
я использую весеннюю версию 3.0.2. Мне нужно загрузить несколько файлов с помощью multiple="multiple"
атрибут файлового браузера, например,
<input type="file" id="myFile" name="myFile" multiple="multiple"/>
(и не используя несколько файловых браузеров что-то вроде того, что указано ответ, это действительно работает, я пробовал).
хотя ни одна версия Internet Explorer не поддерживает этот подход, если не используется соответствующий плагин/виджет jQuery, я не забочусь об этом прямо сейчас (так как большинство других браузеров поддерживают это).
это отлично работает с commons fileupload но в дополнение к использованию RequestMethod.POST
и RequestMethod.GET
методы, я также хочу использовать другие методы запроса поддерживается и предлагается весной, как RequestMethod.PUT
и RequestMethod.DELETE
в своих соответствующих местах. Чтобы это было так, я настроил Spring с HiddenHttpMethodFilter
который идет отлично, как этот вопрос указывает.
но он может загрузить только один файл за раз даже если выбрано несколько файлов в файл-браузер. В классе Spring controller метод отображается следующим образом.
@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
что это List
типа MultipartFile
(он всегда может иметь только один файл за раз).
я мог бы найти стратегию, которая может работать с несколькими файлами этот блог. Я тщательно все просмотрел.
решение ниже раздел РЕШЕНИЕ 2-ИСПОЛЬЗУЙТЕ НЕОБРАБОТАННЫЙ ЗАПРОС говорит,
Если же клиент настаивает на использовании то же имя ввода формы, например как "файлы []" или " файлы’ , а затем заполнить это имя несколькими файлы, то небольшой хак необходимо следующим образом. Как отмечалось выше, Весна 2.5 создает исключение, если оно обнаруживает одно и то же имя ввода формы типа file более одного раза. CommonsFileUploadSupport – класс, который бросает это исключение не является окончательным и метод, который бросает это исключение защищен таким образом, используя чудеса наследования и подкласс один можно просто исправить / изменить логику немного следующим образом. Изменение Я сделал буквально одно слово, представляющее один вызов метода что позволяет нам иметь несколько файлов, входящих в одной форме имя Входа.
он пытается переопределить метод
protected MultipartParsingResult parseFileItems(List fileItems, String encoding){}
абстрактный класс 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 new MultipartParsingResult(multipartFiles, multipartParameters);
вызывает ошибку времени компиляции, потому что первый параметр 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) {}
}
}
причина может быть - это решение касается весенней версии 2.5, и я использую весеннюю версию 3.0.2, которая может быть неуместной для этой версии.
я, однако, попытался заменить Map
С 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
я попытался максимально сократить вопрос, и я не включил ненужный код.
как можно было бы загрузить несколько файлов после того, как Spring был настроен с HiddenHttpMethodFilter
?
этот блог указывает, что это давняя, высокоприоритетная ошибка.
если нет решения относительно версии 3.0.2 (3 или выше), то я должен отключить поддержку Spring навсегда и продолжать использовать commons-fileupolad как предложено третьим решением в этом блоге, опуская PUT, DELETE и другие методы запроса навсегда.
очень мало изменений в коде в parseFileItems()
метод внутри класса MultiCommonsMultipartResolver
может заставить его загружать несколько файлов, но я не смог добиться успеха в своих попытках (снова с весенней версией 3.0.2 (3 или выше)).
2 ответов
для загрузки нескольких файлов в одном запросе я использовал этот код:
у меня такой jsp:
<p>Select files to upload. Press Add button to add more file inputs.</p>
<table>
<tr>
<td><input name="files" type="file" multiple="true"/></td>
</tr>
<tr>
<td><input name="files" type="file" multiple="true"/></td>
</tr>
</table>
<br/><input type="submit" value="Upload" />
загрузка файла класса bean:
import org.springframework.web.multipart.commons.CommonsMultipartFile;
public class FileUploadForm {
private CommonsMultipartFile [] files;
public CommonsMultipartFile[] getFiles() {
return files;
}
public void setFiles( CommonsMultipartFile[] files ) {
this.files = files;
}
}
:
@Controller
@RequestMapping("/upload")
public class FileUploadController {
@RequestMapping(method = RequestMethod.GET)
public String displayForm(ModelMap modelMap) {
modelMap.addAttribute( new FileUploadForm() );
return "uploadForm.jsp";
}
@RequestMapping(method = RequestMethod.POST)
public String save(FileUploadForm uploadForm) {
CommonsMultipartFile[] files = uploadForm.getFiles();
if(files != null && files.length != 0) {
for(MultipartFile file : files) {
System.out.println( file.getOriginalFilename() );
}
}
return "success.jsp";
}
}
этот код позволяет загружать несколько файлов в одном запросе,
и можно получить экземпляр CommonsMultipartFile
для каждого файла.
проблема, упомянутая в вопросе, была основные по состоянию на весну 3.0.4. Таким образом, если вы случайно использовать эту версию или выше (да, это 4.X. x now), вам больше не нужно будет читать этот вопрос/ответ(ы).