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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37922973/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 01:06:20  来源:igfitidea点击:

Spring MVC file upload - Unable to process parts as no multi-part configuration has been provided

springspring-mvctomcatfile-uploadillegalstateexception

提问by kbijoch

So I'm a newbie to Spring and I'm trying to get file upload working for my project (I'm using Spring Tool Suite btw.) and when submitting a form all I'm getting is:

所以我是 Spring 的新手,我正在尝试让文件上传为我的项目工作(我正在使用 Spring Tool Suite 顺便说一句。)并且在提交表单时我得到的是:

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

HTTP 状态 500 - 无法解析多部分 servlet 请求;嵌套异常是 java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided

Stack trace from browser:

来自浏览器的堆栈跟踪:

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.

This is the form tag in jsp:

这是jsp中的表单标签:

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

Input part:

输入部分:

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

Photo is stored in this field in Artist object:

照片存储在艺术家对象中的此字段中:

@Lob
private byte[] photo;

Controller mapping methods:

控制器映射方法:

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

Multipart resolver configuration in servlet-context.xml:

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

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

Filters in web.xml:

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>

Dependencies:

依赖项:

<!-- 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>

I also imported Tomcat's config file context.xml to META-INF/context.xml and edited Context tag like so:

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

<Context allowCasualMultipartParsing="true">

Nothing seems to be working, any help will be greatly appreciated.

似乎没有任何工作,任何帮助将不胜感激。

回答by luis-br

Actually you don't need any filter on the web.xml in order to upload your multipart file with Spring MVC. I've the same configuration in my project and it worked (${spring.version} = 4.3.4.RELEASE):

实际上,您不需要在 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

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 context

弹簧上下文

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

Spring controller

弹簧控制器

@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:/";
        }
    }

回答by Martín Straus

None of the answers address the issue properly. As per Tomcat documentation, on the configuration of allowCasualMultipartParsing:

没有一个答案正确地解决了这个问题。根据Tomcat 文档,关于配置allowCasualMultipartParsing

Set to true if Tomcat should automatically parse multipart/form-data request bodies when HttpServletRequest.getPart* or HttpServletRequest.getParameter* is called, even when the target servlet isn't marked with the @MultipartConfig annotation (See Servlet Specification 3.0, Section 3.2 for details). Note that any setting other than false causes Tomcat to behave in a way that is not technically spec-compliant. The default is false.

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

So, what's the compliant way? Reading the official JEE 6 tutorialgives a hint. If you want to use a spec-compliant way with Servlet 3 or newer, your servlet must have a MultipartConfig. You have three choices, depending on how you configure your servlet:

那么,合规的方式是什么?阅读官方JEE 6 教程给出了一个提示。如果您想对 Servlet 3 或更新版本使用符合规范的方式,您的 servlet 必须有一个MultipartConfig. 根据您配置 servlet 的方式,您有三种选择:

  • With programmatic configuration: context.addServlet(name, servlet).setMultipartConfig(new MultipartConfigElement("your_path").
  • With annotations, annotate the servlet's class with @javax.servlet.annotation.MultipartConfig.
  • With XML configuration, add this to the WEB-INF/web.xmldescriptor, in the section of your servlet:

    <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>
    
  • 使用编程配置:context.addServlet(name, servlet).setMultipartConfig(new MultipartConfigElement("your_path").
  • 使用注释,用@javax.servlet.annotation.MultipartConfig.
  • 使用 XML 配置,将其添加到WEB-INF/web.xml描述符的 servlet 部分:

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

回答by Ramjan Ali

It is straight forward from the exception that no multi-part configuration is found. Though you have provided multipartResolverbean.

从没有找到多部分配置的例外情况来看,这是直接的。尽管您提供了multipartResolverbean。

The problem is that while specifying the MultipartFilter before the Spring Security filter, It tries to get the multipartResolverbean but can't find it. Because it expect the bean name/id as filterMultipartResolverinstead of multipartResolver.

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

Do yourself a favor. Please change the bean configuration like following -

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

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

回答by izogfif

For those who get the same exception for PUTmethod handlers: use POSTinstead. PUTis incompatible with the multi-part.

对于那些在PUT方法处理程序中遇到相同异常的人:POST改为使用。PUT与多部分不兼容。

More details can be found in the respective answer

更多细节可以在相应的答案中找到

回答by susan097

Add In your config file as:

在您的配置文件中添加:

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

}

回答by cralfaro

I have something similar, but what i did is just send a file without mapping it with any attribute in my model, in your case i would modify this:

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

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

In your controller

在您的控制器中

@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
...

回答by ElMurxOr

Had the same issue in a Spring Boot application, this exceptions occur several times:

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

  • org.springframework.web.multipart.MultipartException: Could not parse multipart servlet request; nested exception is
  • java.lang.IllegalStateException: org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field multipartFile exceeds its maximum permitted size of 1048576 bytes
  • 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: The field multipartFile exceeds its maximum permitted size of 1048576 bytes.

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

Get rid of the tomcat exception with this, with copy catting from http://www.mkyong.com/spring-boot/spring-boot-file-upload-example/

用这个摆脱 tomcat 异常,从http://www.mkyong.com/spring-boot/spring-boot-file-upload-example/复制 catting

Tomcat large file upload connection reset. Need to let {@link #containerCustomizer()} work properly, other wise exception will occur several times, RequestMapping for uploadError will fail.

Tomcat 大文件上传连接重置。需要让 {@link #containerCustomizer()} 正常工作,否则会多次发生异常,上传错误的 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;

}

回答by Yachin K

If you are using Tomcat 8.
Configure the following in Tomcat's conf/context.xml

如果你使用的是 Tomcat 8.
在 Tomcat 的 conf/context.xml 中配置以下内容

  • Add allowCasualMultipartParsing="true" attribute to context node
  • Add <Resources cachingAllowed="true" cacheMaxSize="100000" /> inside context node
  • 将 allowCasualMultipartParsing="true" 属性添加到上下文节点
  • 在上下文节点中添加 <Resources cachingAllowed="true" cacheMaxSize="100000" />