SpringBoot中文件上传
老样子,先上代码,再源码分析
SpringBoot里自动装配了MultipartResolver
所以这样我们可以不用加依赖
文件上传类
@RestController
public class UploadController {
SimpleDateFormat sdf = new SimpleDateFormat("/yyyy/MM/dd/");
@PostMapping("/upload")
public String upload(MultipartFile file, HttpServletRequest req) throws IOException {
String format = sdf.format(new Date());
String realPath = req.getServletContext().getRealPath("/img") + format;
File folder = new File(realPath);
if (!folder.exists()) {
folder.mkdirs();
}
String oldName = file.getOriginalFilename();
String newNamme = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
file.transferTo(new File(folder, newNamme));
String url = req.getScheme() + "://" + req.getServerName() + ":" + req.getServerPort() + "/img" + format + newNamme;
return url;
}
}
这里需要讲一下的是req.getServletContext().getRealPath("/")
是默认是从你项目所在的路径,也就是得到的就是你tomcat下webapps下的项目根路径,然后/img就在这个文件夹下,如果没有就会创建。
前端类似这样的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="上传">
</form>
</body>
</html>
或者这样的
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="jquery3.3.1.js"></script>
</head>
<body>
<div id="result"></div>
<input type="file" id="file">
<input type="button" value="上传" onclick="fileupload()">
<script>
function fileupload() {
var file = $("#file")[0].files [0];
var formData = new FormData();
formData.append("file", file);
$.ajax({
type: 'post',
url: '/upload',
data: formData,
processData:false,
contentType:false,
success:function (msg) {
$("#result").html(msg);
}
})
}
</script>
</body>
</html>
设置文件上传的大小, 因为springboot内置tomact的的文件传输默认为1MB
#配置文件传输
spring.servlet.multipart.enabled =true
spring.servlet.multipart.file-size-threshold =0
#单个数据的大小
spring.servlet.multipart.max-file-size = 100Mb
#总数据的大小
spring.servlet.multipart.max-request-size=100Mb
也可以自定义配置类
/**
* 配置上传文件大小的配置
* @return
*/
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
// 单个数据大小
factory.setMaxFileSize("102400KB");
/// 总上传数据大小
factory.setMaxRequestSize("102400KB");
return factory.createMultipartConfig();
}
还可以设置tomcat的文件限制大小
上传文件文件过大时出现如下错误:
org.apache.tomcat.util.http.fileupload.FileUploadBase$FileSizeLimitExceededException: The field pic exceeds its maximum permitted size of 1048576 bytes.
那么为什么可以不用加上文件上传所需依赖了?
答案和以前一样,就是SpringBoot里面有自动装配类
MultipartAutoConfiguration
从启动类注解
而这个spring.factories的路径:
org\springframework\boot\spring-boot-autoconfigure\2.1.6.RELEASE\spring-boot-autoconfigure-2.1.6.RELEASE-sources.jar!\META-INF\spring.factories
@EnableAutoConfiguration 表示启用 Spring 应用程序上下文的自动配置,该注解会自动导入一个名为 AutoConfigurationImportSelector 的类,而这个类会去读取一个名为 spring.factories 的文件, spring.factories 中则定义需要加载的自动化配置类
@Configuration
@ConditionalOnClass({ Servlet.class, StandardServletMultipartResolver.class, MultipartConfigElement.class })
@ConditionalOnProperty(prefix = "spring.servlet.multipart", name = "enabled", matchIfMissing = true)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(MultipartProperties.class)
public class MultipartAutoConfiguration {
private final MultipartProperties multipartProperties;
public MultipartAutoConfiguration(MultipartProperties multipartProperties) {
this.multipartProperties = multipartProperties;
}
@Bean
@ConditionalOnMissingBean({ MultipartConfigElement.class, CommonsMultipartResolver.class })
public MultipartConfigElement multipartConfigElement() {
return this.multipartProperties.createMultipartConfig();
}
@Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
@ConditionalOnMissingBean(MultipartResolver.class)
public StandardServletMultipartResolver multipartResolver() {
StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();
multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily());
return multipartResolver;
}
}
@Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
@ConditionalOnMissingBean(MultipartResolver.class)
public StandardServletMultipartResolver multipartResolver() {
StandardServletMultipartResolver multipartResolver = new StandardServletMultipartResolver();
multipartResolver.setResolveLazily(this.multipartProperties.isResolveLazily());
return multipartResolver;
}
-
@Bean(name = DispatcherServlet.MULTIPART_RESOLVER_BEAN_NAME)
注册bean到Spring容器,name为在DispatcherServlet里的文件上传解析器初始化时的bean名 -
@ConditionalOnMissingBean(MultipartResolver.class)
如果没有MultipartResolver这个bean就默认使用StandardServletMultipartResolver。