我正在尝试使用MultipartFile
实现一个使用Spring上传文件的休息Web服务。我不使用Spring Boot,我的类路径中有commons-fileupload
库。
我阅读的Spring文档说:
您需要在web.xml中使用“multipart-config”部分标记DispatcherServlet,或者在编程Servlet注册中使用javax.servlet.MultipartConfigElement标记,或者在自定义Servlet类可能使用javax.servlet的情况下。 Servlet类上的annotation.MultipartConfig注释...一旦以上述方式之一启用了Servlet 3.0多部分解析,就可以将StandardServletMultipartResolver添加到Spring配置中
因此我将这个bean添加到我的AppConfig
类:
@Bean
public StandardServletMultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
并使用MultipartConfig
注释班级:
@EnableWebMvc
@MultipartConfig(maxFileSize = 5120)
public class AppConfig extends WebMvcConfigurerAdapter{
...
}
但是当我打电话给服务时我得到了这个例外:
Caused by: org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.UnsupportedOperationException: SRVE8020E: Servlet does not accept multipart request
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:111)
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(StandardMultipartHttpServletRequest.java:85)
at org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:76)
at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:112)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207)
at [internal classes]
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at com.ibm.ws.webcontainer.filter.FilterInstanceWrapper.doFilter(FilterInstanceWrapper.java:207)
... 1 more
Caused by: java.lang.UnsupportedOperationException: SRVE8020E: Servlet does not accept multipart request
at com.ibm.ws.webcontainer.srt.SRTServletRequest.prepareMultipart(SRTServletRequest.java:3657)
at [internal classes]
at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:92)
如果我使用CommonsMultipartResolver
代替StandardServletMultipartResolver
,我会收到相同的错误。
这是我初始化我的应用程序的方式:
public class AppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppConfig.class);
context.setServletContext(servletContext);
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcherServlet", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);
FilterRegistration.Dynamic characterEncoding = servletContext.addFilter("CharacterEncodingFilter", characterEncodingFilter);
characterEncoding.addMappingForUrlPatterns(dispatcherTypes, true, "/*");
}
}
我还尝试添加MultipartFilter
,但没有运气。
MultipartFilter multipartFilter = new MultipartFilter();
FilterRegistration.Dynamic multipart = servletContext.addFilter("multipartFilter", multipartFilter);
multipart.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), true, "/*");
这有必要吗?我究竟做错了什么?我想我在整个网络上都在寻找解决方案,但他们都使用MultipartConfigElement
和MultipartConfigFactory
的春季启动。也许问题是我使用服务的方式?
这是我的控制器方法:
@RequestMapping(value = "/upload", method = RequestMethod.POST, consumes = "multipart/form-data" )
public Long uploadAttachment(@RequestParam("cn") String callerName, @RequestParam("cs") String callerService, @RequestParam("file") MultipartFile file)
这就是我消费它的方式:
File file = new File("C:\\Users\\cte0289\\Documents\\Email\\document.docx");
RestTemplate rest = new RestTemplate();
LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
map.add("cn", callerName);
map.add("cs", callerService);
map.add("file", file);
Long response = rest.postForObject(url + "/upload", map, Long.class);
请帮助我不知道还能做什么。
答案 0 :(得分:1)
我想你可能想尝试这样的事情:
public class AppInitializer implements WebApplicationInitializer {
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
context.register(AppConfig.class);
context.setServletContext(servletContext);
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcherServlet", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
dispatcher.setMultipartConfig(getMultipartConfigElement());
CharacterEncodingFilter characterEncodingFilter = new CharacterEncodingFilter();
characterEncodingFilter.setEncoding("UTF-8");
characterEncodingFilter.setForceEncoding(true);
EnumSet<DispatcherType> dispatcherTypes = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD);
FilterRegistration.Dynamic characterEncoding = servletContext.addFilter("CharacterEncodingFilter", characterEncodingFilter);
characterEncoding.addMappingForUrlPatterns(dispatcherTypes, true, "/*");
}
private MultipartConfigElement getMultipartConfigElement(){
MultipartConfigElement multipartConfigElement = new MultipartConfigElement("C:/tmp", 1024*1024*5, 1024*1024*5*5, 1024*1024);
return multipartConfigElement;
}
}
答案 1 :(得分:1)
配置Spring项目以使用java配置处理文件上载的正确方法是: 如果要使用Commons FileUpload库进行配置,只需将此bean包含在Configuration类中,并在类路径中添加jar
@Bean
public CommonsMultipartResolver multipartResolver(){
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(5242880); // set the size limit
return resolver;
}
如果你想用Servlet 3.0配置项目,因为@AlieneilA说你必须在调度程序servlet中设置MultipartConfig
元素:
dispatcher.setMultipartConfig(new MultipartConfigElement("C:/tmp", 1024*1024*5, 1024*1024*5*5, 1024*1024));
并在配置类中包含此bean(在我的例子中为AppConfig):
@Bean
public StandardServletMultipartResolver multipartResolver() {
return new StandardServletMultipartResolver();
}
我将文件插入LinkedMultiValueMap
的方式错了。我不得不使用FileSystemResource
:
File file = new File("C:\\document.doc");
RestTemplate rest = new RestTemplate();
LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<String, Object>();
map.add("param1", param1);
map.add("param2", param2);
map.add("file", new FileSystemResource(file));
Long response = rest.postForObject(url, map, Long.class);
或MockMultipartFile
,如此答案所示:https://stackoverflow.com/a/38270420/6503002
在这种情况下,包括spring mock作为依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-mock</artifactId>
<version>2.0.8</version>
</dependency>
答案 2 :(得分:0)
如果有人为Web应用程序初始化配置扩展AbstractAnnotationConfigDispatcherServletInitializer
类,下面的简单配置将启用MultiPart
功能 -
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletRegistration.Dynamic;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebApplicationInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return null;
}
@Override
protected Class<?>[] getServletConfigClasses() {
return new Class[] { AppConfig.class };
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected void customizeRegistration(Dynamic registration) {
MultipartConfigElement multiPart = new MultipartConfigElement("C:/temp/",
1024 * 1024 * 5, 1024 * 1024 * 10, 1024 * 1024 * 3);
registration.setMultipartConfig(multiPart);
}
}