Postman:解析多部分 servlet 请求失败;嵌套异常是 java.lang.IllegalStateException, MultipartFile, REST

Posted

技术标签:

【中文标题】Postman:解析多部分 servlet 请求失败;嵌套异常是 java.lang.IllegalStateException, MultipartFile, REST【英文标题】:Postman: Failed to parse multipart servlet request; nested exception is java.lang.IllegalStateException, MultipartFile, REST 【发布时间】:2020-03-14 06:47:44 【问题描述】:

我需要通过 Postman 将 image with JSON string 发送到我的 Rest API。我正在使用弹簧启动框架。请看下面的屏幕截图:

还请从应用程序终端查看完整的错误根目录:

2019-11-18 21:04:42.602 ERROR 17468 --- [io-8080-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception

org.springframework.web.multipart.MultipartException: Failed to parse multipart servlet request; nested exception is java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided
    at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.handleParseFailure(StandardMultipartHttpServletRequest.java:124) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:115) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.<init>(StandardMultipartHttpServletRequest.java:88) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.multipart.support.StandardServletMultipartResolver.resolveMultipart(StandardServletMultipartResolver.java:87) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.multipart.support.MultipartFilter.doFilterInternal(MultipartFilter.java:115) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526) [tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139) [tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92) [tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343) [tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408) [tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) [tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1579) [tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-9.0.27.jar:9.0.27]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_221]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_221]
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.27.jar:9.0.27]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_221]
Caused by: java.lang.IllegalStateException: Unable to process parts as no multi-part configuration has been provided
    at org.apache.catalina.connector.Request.parseParts(Request.java:2802) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.catalina.connector.Request.getParts(Request.java:2770) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.apache.catalina.connector.RequestFacade.getParts(RequestFacade.java:1098) ~[tomcat-embed-core-9.0.27.jar:9.0.27]
    at org.springframework.web.multipart.support.StandardMultipartHttpServletRequest.parseRequest(StandardMultipartHttpServletRequest.java:95) ~[spring-web-5.2.1.RELEASE.jar:5.2.1.RELEASE]
    ... 34 common frames omitted

我附在我的控制器类下面:

package MongoSpringREST.controllers;

import MongoSpringREST.models.Movie;
import MongoSpringREST.services.MovieServices;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import java.util.List;

@RestController
@RequestMapping("/Movies")
public class MovieController 

    @Autowired
    private MovieServices movieServices;

    @RequestMapping(value="/singleSave", method=RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public MultipartFile singleSave(@RequestParam(required = true, value = "file") MultipartFile file, @RequestParam(required = true, value = "text") String movie) throws Exception 
        System.out.println("File Description:" + movie);
        return file;
    

Bean 配置类:

package MongoSpringREST.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;
import org.springframework.web.multipart.support.MultipartFilter;

@Configuration
public class MyConfig 

    @Bean
    public CommonsMultipartResolver multipartResolver() 
        CommonsMultipartResolver multipart = new CommonsMultipartResolver();
        multipart.setMaxUploadSize(3 * 1024 * 1024); return multipart;
    

    @Bean
    @Order(0)
    public MultipartFilter multipartFilter() 
        MultipartFilter multipartFilter = new MultipartFilter();
        multipartFilter.setMultipartResolverBeanName("multipartReso‌​lver");
        return multipartFilter;
    

以及 Maven 依赖项:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>MongoSpringREST</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>MongoSpringREST</name>
    <description>Spring REST with MongoDB</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-mongodb</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>de.flapdoodle.embed</groupId>
            <artifactId>de.flapdoodle.embed.mongo</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>commons-fileupload</groupId>
            <artifactId>commons-fileupload</artifactId>
            <version>1.3.3</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

编辑:添加 application.properties:

#max file and request size
spring.http.multipart.max-file-size=10MB
spring.http.multipart.max-request-size=11MB

spring.http.multipart.enabled=true

有人知道问题出在哪里吗?

【问题讨论】:

你在使用zuul吗?可能也和ribbon + zuul有关。 另外,你能显示 POST 吗?也许你可以用 curl 命令伪造它?这通常是“为什么 Spring-boot 不调用我的 requestMapping”的来源。 我没有使用zuul。显示 POST 是什么意思? POST请求是使用API​​。该错误看起来与多部分配置有关 - 这将在您的 application.properties 中。在此处检查您的属性:docs.spring.io/spring-boot/docs/2.0.0.M6/reference/htmlsingle/… 特别是 spring.servlet.multipart.enabled=true 属性 请参阅编辑部分的 application.properties。将其更改为“ spring.servlet.multipart.enabled=true”? 【参考方案1】:

根据https://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-multipart-file-upload-configuration

建议使用容器的内置支持 分段上传,而不是引入额外的依赖 例如 Apache Commons 文件上传。

当您创建 CommonsMultipartResolver 类型的 multipartResolver bean 时,MultipartAutoConfiguration 不会自动配置 MultipartConfigElement bean。

我觉得

要么你应该使用 Spring Boot 自动配置来创建 multipartConfigElement:javax.servlet.MultipartConfigElement multipartResolver:org.springframework.web.multipart.support.StandardServletMultipartResolver beans 或一起创建您自己的CommonsMultipartResolver + MultipartConfigElement bean。

【讨论】:

【参考方案2】:
While Sending Request in Postman 

Header:
Content-Type    multipart/form-data

Body:(form-data)
key file: image (browse image which u want to upload)
Key text:String that u want to sent. 

【讨论】:

虽然这段代码 sn-p 可以解决问题,including an explanation 确实有助于提高您的帖子质量。请记住,您是在为将来的读者回答问题,而这些人可能不知道您提出代码建议的原因。

以上是关于Postman:解析多部分 servlet 请求失败;嵌套异常是 java.lang.IllegalStateException, MultipartFile, REST的主要内容,如果未能解决你的问题,请参考以下文章

快速“预览”传入的多部分请求

当前请求不是多部分请求 Spring Boot 和 Postman(上传 json 文件加上额外字段)

Servlet从tomcat 7中的多部分表单获取参数[重复]

使用 Postman Chrome 扩展发送多部分/混合内容

PrimeFaces 4.0/JSF 2.2.x 中的文件上传不适用于 AJAX - javax.servlet.ServletException:请求内容类型不是多部分/表单数据

1-1 postman工具简介