0

我有一个工作的 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/upload 表单显示但是当我单击提交按钮时我得到了。错误信息

HTTP 状态 403 - 在请求参数“_csrf”或标头“X-CSRF-TOKEN”上发现无效的 CSRF 令牌“null”。

我去禁用 csrf 以查看如果禁用跨站点请求伪造(“.csrf().disable()”),表单是否可以正常工作。IE

   @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: Unable to process parts 因为没有提供多部分配置

它说“没有提供多部分配置”,但我确实有配置 multipartConfigElement 的配置文件,即

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

我的 Application 类上方还有 @ComponentScan 注释和 @EnableAutoConfiguration ,即:

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

当应用程序启动时,我列出了由 spring 管理的所有 bean,并且我确实看到 bean“multipartResolver”正在启动。

与 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 中设置为“/”,这是我在部署程序集配置中的唯一条目。

我之前读过,旧的 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>

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

https://github.com/TheDictator/sArchitecture

为了重现登录:

用户名:admin2 密码:#passwordD

然后去

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

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

4

1 回答 1

1

DispatcherServlet自己注册(而不是让 Spring Boot 来注册),因此您必须注意为其添加多部分配置。Spring Boot 仅将多部分配置添加到ServletRegistrationBeans它自己创建的配置中(请参见此处),因此如果您创建自己的配置,则必须处理它。希望 APIServletRegistrationBean足够清楚,即使不是很明显,也可以暗示这一点

于 2014-05-17T05:37:13.793 回答