我有一个工作的 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;
}
我自己还没有回答这个问题,因为我还不明白为什么这种和平的代码会破坏上传功能。