spring mvc上传文件表单同时传值的问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spring mvc上传文件表单同时传值的问题相关的知识,希望对你有一定的参考价值。

参考技术A 当在上传表单中设置了 enctype="multipart/form-data" 时post传过去的字符串的值为null,会报 HTTP Status 400 - Required String parameter 'description' is not present 错误。
解决方案:
1、首先在pom.xml中添加

然后在applicationContext.xml中添加即可解决,这样的话spring会对表单的数据进行处理,就算使用了enctype="multipart/form-data"进行传值也能拿到数据

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

【中文标题】Spring MVC 文件上传 - 由于未提供多部分配置,因此无法处理部分【英文标题】:Spring MVC file upload - Unable to process parts as no multi-part configuration has been provided 【发布时间】:2016-10-21 17:39:30 【问题描述】:

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

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

来自浏览器的堆栈跟踪:

类型异常报告 消息无法解析多部分 servlet 请求;嵌套异常是 java.lang.IllegalStateException: Unable to process parts 因为没有提供多部分配置 描述 服务器遇到一个内部错误,阻止它完成这个请求。 例外 org.springframework.web.multipart.MultipartException:无法解析多部分 servlet 请求;嵌套异常是 java.lang.IllegalStateException: Unable to process parts 因为没有提供多部分配置 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) 根本原因 java.lang.IllegalStateException:无法处理部分,因为没有提供多部分配置 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 Apache Tomcat/8.0.27 日志中提供了根本原因的完整堆栈跟踪。

这是jsp中的form标签:

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

似乎没有任何效果,任何帮助将不胜感激。

【问题讨论】:

回复***.com/a/24267170/755401 我在this link回答了,我的问题解决了 【参考方案1】:

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

更多详情请见respective answer

【讨论】:

【参考方案2】:

在你的配置文件中添加:

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


【讨论】:

【参考方案3】:

没有一个答案能正确解决问题。根据Tomcat documentation,关于allowCasualMultipartParsing的配置:

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

那么,合规的方式是什么?阅读官方JEE 6 tutorial 给出了提示。如果您想在 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】:

在 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() 正常工作,否则会出现多次异常,RequestMapping for uploadError 会失败。

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


【讨论】:

【参考方案5】:

没有找到多部分配置的例外情况很简单。尽管您提供了 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>

【讨论】:

作为参考,我用它作为别名:&lt;bean id="multipartResolver" name="filterMultipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"&gt; &lt;property name="maxUploadSize" value="10000000"/&gt; &lt;/bean&gt; 谢谢:)【参考方案6】:

如果您使用的是 Tomcat 8。 在Tomcat的conf/context.xml中配置如下

将 allowCasualMultipartParsing="true" 属性添加到上下文节点 在上下文节点中添加

【讨论】:

【参考方案7】:

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

弹簧上下文

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

弹簧控制器

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

【讨论】:

【参考方案8】:

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

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

【讨论】:

不幸的是它没有工作,仍然出现同样的错误。 @kbijoch 仅出于测试目的,从您的控制器中删除 Valid 。你所有的配置看起来都正确,我有相同的并且正在工作 仍然没有成功,但感谢您的帮助。文件名重要吗? 我不这么认为,但你可以尝试使用一个小于 1mb 的小文件并命名为 test.log 或类似的东西。奇怪我有相同的代码,让我再检查一遍 我尝试了一些具有不同扩展名的文件,仍然是同样的问题。可能与环境有关?

以上是关于spring mvc上传文件表单同时传值的问题的主要内容,如果未能解决你的问题,请参考以下文章

Spring MVC 多文件上传与 HTML5 多文件表单功能

Spring MVC,文件上传

在 Angular 2 和 Spring MVC 中上传带有其他表单字段的文件

如何使用多部分/表单和分块编码在 spring mvc 中接收文件上传?

spring-mvc实现网页文件上传

在 Spring Boot App 中使用 Jquery 和 FormData 提交表单字段并上传 File 到 Spring MVC Controller