Spring MVC文件上传 - 由于未提供多部件配置,因此无法处理部件

时间:2016-06-20 12:46:40

标签: spring spring-mvc tomcat file-upload illegalstateexception

所以,我是Spring的新手,我试图让我的项目上传文件(我使用Spring Tool Suite顺便说一句。)并且在提交表单时我都会这样做。得到的是:

  

HTTP状态500 - 无法解析多部分servlet请求;嵌套异常是java.lang.IllegalStateException:无法处理部件,因为没有提供多部件配置

来自浏览器的堆栈跟踪:

type Exception report

message Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided

description The server encountered an internal error that prevented it from fulfilling this request.

exception

org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided
    org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:100)
    org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.(StandardMultipartHttpServletRequest.java:78)
    org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:75)
    org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:108)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)
root cause

java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided
    org.apache.catalina.connector.Request.parseParts(Request.java:2676)
    org.apache.catalina.connector.Request.getParts(Request.java:2643)
    org.apache.catalina.connector.RequestFacade.getParts(RequestFacade.java:1083)
    org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:85)
    org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.(StandardMultipartHttpServletRequest.java:78)
    org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:75)
    org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:108)
    org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:106)

note The full stack trace of the root cause is available in the Apache Tomcat/8.0.27 logs.

这是jsp中的表单标记:

<form:form class="form-horizontal" role="form" method="post"
            action="newArtist.html" modelAttribute="artist" enctype="multipart/form-data">

输入部分:

<div class="form-group">
    <div class="col-lg-3">
        <label for="photo">Artist photo:</label>
        <form:input type="file" id="photo" path="photo"></form:input>
    </div>
</div>

照片存储在Artist对象中的此字段中:

@Lob
private byte[] photo;

控制器映射方法:

@RequestMapping(value = "/newArtist", method = RequestMethod.GET)
public String showAddArtistForm(Model model)
{
    model.addAttribute("artist", new Artist());
    return "newArtist";
}

@RequestMapping(value = "/newArtist", method = RequestMethod.POST)
public String addArtist(@ModelAttribute("artist") @Valid Artist artist, BindingResult result,
        @RequestParam("photo") MultipartFile photo) throws IOException
{   
    if (result.hasErrors())
        return "newArtist";

    if(photo.getBytes() != null)
        artist.setPhoto(photo.getBytes());

    artistService.addArtist(artist);

    return "redirect:artists.html";
}

servlet-context.xml中的多部分解析器配置:

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="10000000"/>
</bean>

在web.xml中过滤:

<filter>
    <filter-name>MultipartFilter</filter-name>
    <filter-class>org.springframework.web.multipart.support.MultipartFilter</filter-class>
</filter>
<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>MultipartFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

依赖关系:

<!-- Apache Commons FileUpload -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.1</version>
    </dependency>

    <!-- Apache Commons IO -->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.4</version>
    </dependency>

我还将Tomcat的配置文件context.xml导入到META-INF / context.xml并编辑了Context标签,如下所示:

<Context allowCasualMultipartParsing="true">

似乎没有任何效果,我们将非常感谢任何帮助。

8 个答案:

答案 0 :(得分:4)

实际上,您不需要在web.xml上使用任何过滤器,以便使用Spring MVC上传您的多部分文件。我在我的项目中使用了相同的配置并且工作正常($ {spring.version} = 4.3.4.RELEASE):

POM

     <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-web</artifactId>
        <version>${spring.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-webmvc</artifactId>
        <version>${spring.version}</version>
    </dependency>

    <!-- Apache Commons FileUpload -->
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.3.2</version>
    </dependency>

    <!-- Apache Commons IO -->
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.5</version>
    </dependency>

HTML

    <form method="POST" enctype="multipart/form-data" action="uploadAction">
        <table>
            <tr><td>File to upload:</td><td><input type="file" name="file" /></td></tr>
            <tr><td></td><td><input type="submit" value="Upload" /></td></tr>
        </table>
    </form>

Spring上下文

<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="10000000"/>
</bean>

Spring控制器

@PostMapping("/uploadAction")
    public String handleFileUpload(@RequestParam("file") MultipartFile file,
            RedirectAttributes redirectAttributes) {

        File out = new File("outputfile.pdf");
        FileOutputStream fos = null;

        try {
            fos = new FileOutputStream(out);

            // Writes bytes from the specified byte array to this file output stream 
            fos.write(file.getBytes());
            System.out.println("Upload and writing output file ok");
        } catch (FileNotFoundException e) {
            System.out.println("File not found" + e);
        } catch (IOException ioe) {
            System.out.println("Exception while writing file " + ioe);
        } finally {
            // close the streams using close method
            try {
                if (fos != null) {
                    fos.close();
                }
            } catch (IOException ioe) {
                System.out.println("Error while closing stream: " + ioe);
            }

            //storageService.store(file);
            redirectAttributes.addFlashAttribute("message",
                    "You successfully uploaded " + file.getOriginalFilename() + "!");

            return "redirect:/";
        }
    }

答案 1 :(得分:3)

除了没有找到多部件配置之外,它是直接的。虽然您提供了 multipartResolver bean。

问题是,在Spring Security过滤器之前指定MultipartFilter时,它会尝试获取 multipartResolver bean,但无法找到它。因为它希望bean名称/ id为 filterMultipartResolver 而不是 multipartResolver

帮自己一个忙。请更改bean配置,如下所示 -

<bean id="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
    <property name="maxUploadSize" value="10000000"/>
</bean>

答案 2 :(得分:1)

我有类似的东西,但我所做的只是发送一个文件而不用我的模型中的任何属性映射它,在你的情况下我会修改它:

<div class="form-group">
    <div class="col-lg-3">
        <label for="photo">Artist photo:</label>
        <input type="file" id="photo" name="file"/>
    </div>
</div>

在您的控制器中

@RequestMapping(value = "/newArtist", method = RequestMethod.POST)
public String addArtist(@ModelAttribute("artist") @Valid Artist artist, BindingResult result,
    @RequestParam("file") MultipartFile file) throws IOException
//Here read the file and store the bytes into your photo attribute
...

答案 3 :(得分:1)

没有一个答案可以正确解决问题。根据{{​​3}},allowCasualMultipartParsing的配置:

  

如果在调用HttpServletRequest.getPart *或HttpServletRequest.getParameter *时Tomcat应自动解析multipart / form-data请求体,则设置为true,即使目标servlet未使用@MultipartConfig注释进行标记(请参阅Servlet)规范3.0,第3.2节(详情)。 请注意,除false之外的任何设置都会导致Tomcat以不符合技术规范的方式运行。默认值为false。

那么,符合标准的方式是什么?阅读官方Tomcat documentation给出了一个提示。如果要对Servlet 3或更高版本使用符合规范的方法,则servlet必须具有MultipartConfig。您有三种选择,具体取决于您配置servlet的方式:

  • 使用程序化配置:context.addServlet(name, servlet).setMultipartConfig(new MultipartConfigElement("your_path")
  • 使用注释,使用@javax.servlet.annotation.MultipartConfig注释servlet的类。
  • 使用XML配置,将其添加到servlet部分的WEB-INF/web.xml描述符中:

    <multipart-config>
         <location>/tmp</location>
         <max-file-size>20848820</max-file-size>
         <max-request-size>418018841</max-request-size>
         <file-size-threshold>1048576</file-size-threshold>
    </multipart-config>
    

答案 4 :(得分:1)

在配置文件中添加:

@Bean(name = "multipartResolver")
public CommonsMultipartResolver CanBeAnyName() { 
//configuration

}

答案 5 :(得分:0)

在Spring Boot应用程序中遇到同样的问题,这种异常会多次发生:

  • org.springframework.web.multipart.MultipartException:无法解析多部分servlet请求;嵌套异常是
  • java.lang.IllegalStateException:org.apache.tomcat.util.http.fileupload.FileUploadBase $ FileSizeLimitExceededException:字段multipartFile超出其允许的最大大小1048576字节

org.apache.tomcat.util.http.fileupload.FileUploadBase $ FileSizeLimitExceededException:字段multipartFile超出其允许的最大大小1048576字节。

使用http://www.mkyong.com/spring-boot/spring-boot-file-upload-example/

复制捕获,摆脱tomcat异常

Tomcat大文件上传连接重置。需要让{@link #containerCustomizer()}正常工作,其他明智的异常会多次发生,uploadError的RequestMapping将失败。

@Bean
public TomcatEmbeddedServletContainerFactory tomcatEmbedded() {

    TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();

    tomcat.addConnectorCustomizers((TomcatConnectorCustomizer) connector -> {
        if ((connector.getProtocolHandler() instanceof AbstractHttp11Protocol<?>)) {
            //-1 means unlimited
            ((AbstractHttp11Protocol<?>) connector.getProtocolHandler()).setMaxSwallowSize(-1);
        }
    });

    return tomcat;

}

答案 6 :(得分:0)

对于那些为PUT方法处理程序获得相同异常的人:改为使用POSTPUT与多部分内容不兼容。

更多详细信息,请访问respective answer

答案 7 :(得分:-1)

如果您使用的是Tomcat 8 在Tomcat的conf / context.xml

中配置以下内容
  • 添加allowCasualMultipartParsing =&#34; true&#34;属性到上下文节点
  • 添加&lt;资源cachingAllowed =&#34; true&#34; cacheMaxSize =&#34; 100000&#34; /&GT;内部上下文节点