Chú ý: Câu hỏi này là hoàn toàn vô dụng đối với bất kỳ phiên bản mùa xuân cao hơn 3.0.4 là vấn đề thảo luận trong chủ đề này đã fixed trong phiên bản đó từ lâu và không còn có thể tái sản xuất được trong các phiên bản tiếp theo của mùa xuân.Đang tải lên nhiều file sử dụng Spring MVC 3.0.2 sau HiddenHttpMethodFilter đã được kích hoạt
Tôi đang sử dụng phiên bản Spring 3.0.2. Tôi cần phải upload nhiều file bằng cách sử dụng multiple="multiple"
thuộc tính của một trình duyệt tập tin chẳng hạn như,
<input type="file" id="myFile" name="myFile" multiple="multiple"/>
(và không sử dụng nhiều trình duyệt tập tin giống như một tuyên bố bằng this answer, nó thực sự làm việc tôi đã cố gắng).
Mặc dù không có phiên bản nào của Internet Explorer hỗ trợ phương pháp này trừ khi plugin/tiện ích jQuery thích hợp được sử dụng, tôi không quan tâm đến nó ngay bây giờ (vì hầu hết các trình duyệt khác đều hỗ trợ tính năng này).
này hoạt động tốt với commons fileupload nhưng ngoài việc sử dụng RequestMethod.POST
và RequestMethod.GET
phương pháp, tôi cũng muốn sử dụng phương pháp yêu cầu khác được hỗ trợ và đề nghị của mùa xuân như RequestMethod.PUT
và RequestMethod.DELETE
ở những nơi thích hợp riêng của họ. Để làm được điều này, tôi đã định cấu hình Spring bằng HiddenHttpMethodFilter
, hoạt động tốt như chỉ số this question.
nhưng nó chỉ có thể tải lên một tệp tại một thời điểm mặc dù nhiều tệp trong trình duyệt tệp được chọn. Trong lớp trình điều khiển Spring, một phương thức được ánh xạ như sau.
@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());
}
}
Ngay cả với các thông số yêu cầu @RequestParam("myFile") List<MultipartFile> files
mà là một List
loại MultipartFile
(nó luôn luôn chỉ có một tập tin tại một thời điểm).
Tôi có thể tìm thấy chiến lược có khả năng hoạt động với nhiều tệp on this blog. Tôi đã trải qua nó một cách cẩn thận.
Giải pháp dưới phần SOLUTION 2 - SỬ DỤNG YÊU CẦU RAW nói,
Nếu Tuy nhiên khách hàng khẳng định về việc sử dụng tên đầu vào hình thức tương tự như vậy là 'file []' hoặc 'files' và sau đó điền tên đó với nhiều tập tin sau đó một hack nhỏ là cần thiết như sau. Như đã lưu ý ở trên, Spring 2.5 ném một ngoại lệ nếu nó phát hiện cùng một tên đầu vào của tệp kiểu tệp nhiều lần. CommonsFileUploadSupport - lớp mà ném ngoại lệ đó không phải là cuối cùng và các method mà ném ngoại lệ mà được bảo vệ để sử dụng những điều kỳ diệu của thừa kế và subclassing một chỉ đơn giản là có thể sửa chữa/sửa đổi logic một chút như sau. Thay đổi Tôi đã thực hiện theo nghĩa đen là một từ đại diện cho một lời gọi phương thức cho phép chúng tôi có nhiều tệp đến dưới cùng một hình thức tên đầu vào.
Nó cố gắng để ghi đè phương pháp
protected MultipartParsingResult parseFileItems(List fileItems, String encoding){}
của lớp trừu tượng CommonsFileUploadSupport
bằng cách mở rộng các lớp CommonsMultipartResolver
như,
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);
}
}
gì xảy ra là dòng cuối cùng trong phương pháp parseFileItems()
(báo cáo trả lại) tức là
return new MultipartParsingResult(multipartFiles, multipartParameters);
gây ra một lỗi thời gian biên dịch bởi vì các tham số đầu tiên multipartFiles
là một loại Map
thực hiện bởi HashMap
nhưng trong thực tế, nó đòi hỏi một tham số có kiểuMultiValueMap<String, MultipartFile>
Đó là một nhà xây dựng của một lớp tĩnh bên trong trừu tượng lớp CommonsFileUploadSupport
,
public abstract class CommonsFileUploadSupport {
protected static class MultipartParsingResult {
public MultipartParsingResult(MultiValueMap<String, MultipartFile> mpFiles, Map<String, String[]> mpParams) {}
}
}
lý do có thể là - giải pháp này là về phiên bản mùa xuân 2,5 và tôi đang sử dụng phiên bản mùa xuân 3.0.2 mà có thể không thích hợp cho phiên bản này.
tuy nhiên tôi đã cố gắng để thay thế Map
với MultiValueMap
theo nhiều cách khác nhau như thể hiện trong các phân đoạn sau của mã,
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);
nhưng không thành công. Tôi không chắc chắn cách thay thế Map
bằng MultiValueMap
và thậm chí làm như vậy cũng có thể hoạt động. Sau khi làm điều này, trình duyệt cho thấy phản ứng Http,
HTTP Status 400-
báo cáo Loại Status
nhắn
Mô tả Yêu cầu gửi của khách hàng là cú pháp không chính xác ().
Apache Tomcat/6.0.26
Tôi đã cố gắng để rút ngắn câu hỏi càng tốt như tôi có thể và tôi đã không bao gồm mã không cần thiết.
Làm cách nào để có thể tải lên nhiều tệp sau khi Spring được định cấu hình với HiddenHttpMethodFilter
?
Blog đó cho biết rằng đó là lỗi lâu dài, có mức độ ưu tiên cao.
Nếu không có giải pháp nào liên quan đến phiên bản 3.0.2 (3 hoặc cao hơn) thì tôi phải tắt hỗ trợ Spring mãi mãi và tiếp tục sử dụng commons-fileupolad như được đề xuất bởi giải pháp thứ ba trên blog đó bỏ qua yêu cầu PUT, DELETE và yêu cầu khác phương pháp mãi mãi.
thay đổi rất ít để mã kiểm tra vào parseFileItems()
phương pháp bên trong lớp MultiCommonsMultipartResolver
có thể làm cho nó upload nhiều file nhưng tôi không thể thành công trong nỗ lực của tôi (một lần nữa với phiên bản mùa xuân 3.0.2 (3 trở lên)).
[Vấn đề Jira] (https://jira.springsource.org/browse/SPR-2784?page=com.atlassian.jira.plugin.system.issuetabpanels%25253Aall-tabpanel) được đề cập trong bài đăng trên blog được khắc phục kể từ phiên bản 3.0.4, bạn có thể thử nâng cấp không? –
@RC - Cảm ơn bạn đã liên kết. Tôi có một ứng dụng lớn hơn một nửa đã hoàn thành. Thay đổi khuôn khổ có thể yêu cầu thay đổi mã ở nhiều nơi, vì vậy, tôi có thể nghĩ về một phiên bản cao hơn cho các dự án trong tương lai (tôi nên biết nó trước khi tôi bắt đầu). Cảm ơn bạn. – Tiny
3.0.2 đến 3.0.4 là một nâng cấp nhỏ (chủ yếu là sửa lỗi nếu tôi nhìn vào số phiên bản), do đó, nó sẽ không đau. Bạn nên thử nó và đi cho nó nếu nó hoạt động –