我有一个有效的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;
}
我还没有回答这个问题我自己,因为我还不明白为什么代码的安静会破坏上传功能。
答案 0 :(得分:1)
您自己注册DispatcherServlet
(而不是让Spring Boot执行此操作),因此您必须注意为其添加多部分配置。 Spring Boot仅将多部分配置添加到它自己创建的ServletRegistrationBeans
(see here),因此如果您创建自己的配置,则需要处理它。希望ServletRegistrationBean
的API足够清晰,即使不是很明显,也是隐含的