簡體   English   中英

Spring休息MultiPart文件上傳與Java配置沒有Spring啟動

[英]Spring rest MultiPart file upload with Java configuration without Spring boot

我正在嘗試使用Spring配置使用MultipartFile上傳文件的休息Web服務。 我不使用Spring Boot,我的classpath中有commons-fileupload庫。

我讀了Spring文檔說:

你需要在web.xml中使用“multipart-config”部分標記DispatcherServlet,或者在編程Servlet注冊中使用javax.servlet.MultipartConfigElement標記,或者在自定義Servlet類的情況下使用javax.servlet.annotation.MultipartConfig標記Servlet類上的注釋...一旦使用上述方法之一啟用了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, "/*");

這有必要嗎? 我究竟做錯了什么? 我想我在整個網絡上搜索一個解決方案,但他們都使用Springpart與MultipartConfigElementMultipartConfigFactory 也許問題是我使用服務的方式?

這是我的控制器方法:

@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);

請幫助我不知道還能做什么。

我想你可能想嘗試這樣的事情:

        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;
        }
    }

配置Spring項目以使用java配置處理文件上載的正確方法是:如果要使用Commons FileUpload庫配置它,則只需在Configuration類中包含此bean並在類路徑中添加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);

或者這個答案建議的MockMultipartFilehttpsMockMultipartFile

在這種情況下,包括spring mock作為依賴:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-mock</artifactId>
    <version>2.0.8</version>
</dependency>

如果有人正在為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);
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM