Spring-Boot + Tomcat 8.0.3 FileUpload错误无法处理部件,因为未提供多部件配置

时间:2014-05-12 08:33:03

标签: file-upload spring-boot embedded-tomcat-8

我有一个有效的spring-boot mvc应用程序,我正在尝试集成文件上传选项。根据手册,我配置了以下模板:

/src/main/resource/templates/fileUpload.html

<!DOCTYPE html>
<html layout:decorator="layout">

<head> 
<title>syncServer File upload example</title>
</head>
  <body>
    <div layout:fragment="content">

    <div >
        <form th:action="@{/upload}" enctype="multipart/form-data" th:method="post">
            <fieldset>
                     <legend>File to upload:</legend>
                     <input type="file" name="myFile" />
                     <label>Name :</label>
                     <input type="text" name="myName"/>
                     <input type="submit" />
            </fieldset>
    </form>
    </div>

    </div>

  </body>
</html>

当我登录然后调用http:/127.0.0.5:8080 /上传表单显示但是当我点击我收到的提交按钮时。错误消息

  

HTTP状态403 - 无效的CSRF令牌&#39; null&#39;在请求中找到了   参数&#39; _csrf&#39;或标题&#39; X-CSRF-TOKEN&#39;。

我去了并禁用了csrf,以便在禁用跨站点请求伪造(&#34; .csrf()。disable()&#34;)时查看表单是否可以正常工作。 即

   @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
//          .headers().disable()
            .authorizeRequests()
                .antMatchers("/resources/css/**","/register", "/resources/img/**" , "/resources/js/**", "/resources/pdf/**").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

当我在csrf被禁用期间尝试上传另一个文件时,我又遇到了另一个错误,即:

  

HTTP状态500 - 请求处理失败;嵌套异常是   org.springframework.web.multipart.MultipartException:无法解析   多部分servlet请求;嵌套异常是   java.lang.IllegalStateException:无法将部件处理为no   已提供多部分配置

它说&#34;没有提供多部分配置&#34;但我确实有配置文件来配置multipartConfigElement,即

@Configuration
public class FileUpload {
    @Bean
    MultipartConfigElement multipartConfigElement() {
        MultiPartConfigFactory factory = new MultiPartConfigFactory();
        factory.setMaxFileSize("600KB");
        factory.setMaxRequestSize("600KB");
        return factory.createMultipartConfig();
    }
}

我的应用程序类上面还有@ComponentScan anotation和@EnableAutoConfiguration,例如:

@ComponentScan(basePackages = "org.syncServer.*")
@Configuration
@EnableWebSocketMessageBroker
@EnableAutoConfiguration
public class Application extends SpringBootServletInitializer {
...
}

当应用程序启动时,我列出了由spring管理的所有bean,我确实看到了bean&#34; multipartResolver&#34;正在发起。

与fileUpload.html关联的控制器:

@Controller
public class FileUploadController {


    @RequestMapping(value="/upload", method=RequestMethod.GET)
    public String provideUploadInfo() {
        return "fileUpload";
    }


    @RequestMapping(value="/upload", method=RequestMethod.POST)
    public @ResponseBody String handleFileUpload(@RequestParam("myName") String myName, 
            @RequestParam("myFile") MultipartFile myFile){
        if (!myFile.isEmpty()) {
            try {
                byte[] bytes = myFile.getBytes();
                BufferedOutputStream stream = 
                        new BufferedOutputStream(new FileOutputStream(new File(myName + "-uploaded")));
                stream.write(bytes);
                stream.close();
                return "Successfully uploaded " + myName + " into " + myName + "-uploaded !";
            } catch (Exception e) {
                return "Failed to upload " + myName + " => " + e.getMessage();
            }
        } else {
            return "Failed to upload " + myName + " empty file.";
        }
    }

}

当我在get方法中设置断点时,我看到该方法被命中并返回fileUpload.html视图。但是post方法根本没有被击中。

我不知道这是否相关,但我已将Project-Properties-Deployment程序集 - / src / main / resources设置为&#34; /&#34;这是我在部署程序集配置中唯一的条目。

我之前已经阅读过旧的spring-boot RC版本中存在文件上传的错误。我目前正在使用spring-boot 1.0.2.RELEASE。 我的pom文件

<?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 http://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>1.0.2.RELEASE</version>
    </parent>


    <groupId>sync</groupId>
    <artifactId>syncServer</artifactId>
    <name>syncServer</name>

    <!-- When removing the parent project configuration you have to explicitly set the dependencies version -->
    <dependencies>

        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>${hibernate}</version>
        </dependency>
        <dependency>
            <groupId>postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <version>9.1-901.jdbc4</version>
        </dependency>

        <dependency>
            <groupId>javax.validation</groupId>
            <artifactId>validation-api</artifactId>
            <version>1.1.0.Final</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
        </dependency>
        <dependency>
            <groupId>commons-dbcp</groupId>
            <artifactId>commons-dbcp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-messaging</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf-spring4</artifactId>
        </dependency>



        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-websocket</artifactId>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-core</artifactId>
            <version>${tomcat8.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-websocket</artifactId>
            <version>8.0.3</version>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>

        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-websocket</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-web</artifactId>
            <version>3.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-config</artifactId>
            <version>3.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-core</artifactId>
            <version>3.2.2.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf</groupId>
            <artifactId>thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity3</artifactId>
        </dependency>
        <dependency>
            <groupId>nz.net.ultraq.thymeleaf</groupId>
            <artifactId>thymeleaf-layout-dialect</artifactId>
            <version>1.2.1</version>
        </dependency>
    </dependencies>

    <version>1.0-SNAPSHOT</version>

    <build>
        <defaultGoal>test</defaultGoal>
        <plugins>

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

            </plugin>

            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>

                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <configuration>
                    <useSystemClassLoader>false</useSystemClassLoader>
                </configuration>
            </plugin>


        </plugins>



    </build>



  <repositories>
    <repository>
        <id>spring-milestones</id>
        <name>Spring Milestones</name>
        <url>http://repo.spring.io/milestone</url>
        <snapshots>
            <enabled>false</enabled>
        </snapshots>
    </repository>
</repositories>

    <pluginRepositories>
        <pluginRepository>
            <id>spring-snapshots</id>
            <url>http://repo.spring.io/libs-snapshot</url>
            <snapshots><enabled>true</enabled></snapshots>
        </pluginRepository>

        <pluginRepository>
            <id>spring-milestones</id>
            <url>http://repo.spring.io/milestone</url>
        </pluginRepository>


    </pluginRepositories>

    <properties>
        <java-version>1.7</java-version>
        <spring-version>4.0.2.RELEASE</spring-version>
        <org.aspectj-version>1.6.10</org.aspectj-version>
        <org.slf4j-version>1.7.6</org.slf4j-version>
        <start-class>org.syncServer.core.Application</start-class>
        <springBootVersion>1.0.2.RELEASE</springBootVersion>
        <tomcat8.version>8.0.3</tomcat8.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <hibernate>4.3.1.Final</hibernate>
    </properties>



</project>

这里添加的是评论中要求的完整HTML代码:

<!DOCTYPE html>


<html>
  <head>
<title>Task List - syncServer File upload example</title>

    <link rel="stylesheet" type="text/css" media="all" href="/css/syncServer.css" />
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
    <script src="/js/jquery.js"></script>



</head>

  <body>
     <div class="navbar navbar-inverse navbar-fixed-top">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".nav-collapse">
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">My project</a>
        </div>
        <div class="navbar-collapse collapse">
          <ul class="nav navbar-nav">
            <li class="active"><a href="/">Home</a></li>
            <li><a href="/message">OpenSource</a></li>
            <li><a href="/task">Documents</a></li>
          </ul>
          <ul class="nav navbar-nav navbar-right">
<!--             <li th:if="${#authorization.expression('!isAuthenticated()')}"> -->
<!--               <a href="/signin" th:href="@{/signin}">Sign in</a> -->
<!--             </li> -->
<!--             <li th:if="${#authorization.expression('isAuthenticated()')}"> -->
<!--               <a href="/logout" th:href="@{/logout}">Logout</a> -->
<!--             </li> -->
          </ul>
        </div>
      </div>
    </div>
    <div class="container">
      <div>

    <div>
        <form enctype="multipart/form-data" method="post" action="/upload">
            <fieldset>
                     <legend>File to upload:</legend>
                     <input type="file" name="myFile" />
                     <label>Name :</label>
                     <input type="text" name="myName" />
                     <input type="submit" />
            </fieldset>
    </form>
    </div>

    </div>
      <div>
      © 2014
      <br />
      Autumn, Winter, Summer , Spring is always inside.
    </div>
    </div>
  </body>
</html>

添加2链接到显示问题的工作maven项目

https://github.com/TheDictator/sArchitecture

为了重现登录:

用户名:admin2密码:#passworD

然后转到

http://127.0.0.5:8080/upload

上面描述的错误消息见。

增加3

当我删除我之前在应用程序类中的入口点邮件之前声明的bean时,我的特定问题得到解决,即

@Bean
public ServletRegistrationBean dispatcherRegistration() {

    System.out.println("SERVLET REGISTRATION");
    ServletRegistrationBean registration = new ServletRegistrationBean(
            dispatcherServlet());

    System.out.println("SERVLET REGISTERED NAME is: "
            + registration.getServletName().toString());
    registration.addUrlMappings("/");

    return registration;
}

我还没有回答这个问题我自己,因为我还不明白为什么代码的安静会破坏上传功能。

1 个答案:

答案 0 :(得分:1)

您自己注册DispatcherServlet(而不是让Spring Boot执行此操作),因此您必须注意为其添加多部分配置。 Spring Boot仅将多部分配置添加到它自己创建的ServletRegistrationBeanssee here),因此如果您创建自己的配置,则需要处理它。希望ServletRegistrationBean的API足够清晰,即使不是很明显,也是隐含的