一、前期配置
同样不需要额外配置添加一个 web 功能模块即可
二、单文件上传
上传页面 index.html
位置放在了 static 目录下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--enctype:encodetype编码类型-->
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="提交">
</form>
</body>
</html>
知识点:enctype="multipart/form-data"
enctype 意思是encodetype就是编码类型
multipart/form-data
是指表单数据有多部分构成,既有文本数据,又有文件等二进制数据的意思。
需要注意的是:默认情况下,enctype的值是application/x-www-form-urlencoded
,不能用于文件上传,只有使用了multipart/form-data,才能完整的传递文件数据
FileUploadController:
@RestController
public class FileUploadController {
private static final Logger log = LoggerFactory.getLogger(FileUploadController.class);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
//MultipartFile 这个类一般是用来接受前台传过来的文件
@PostMapping("/upload")
public Map<String, String> upload(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IOException {
//日志打印文件信息
log.info("[文件类型] - [{}]", file.getContentType());
log.info("[文件名称] - [{}]", file.getOriginalFilename());
log.info("[文件大小] - [{}]", file.getSize());
//设置存储位置
String format = sdf.format(new Date());
String path = "D:\\flv\\" + format;
System.out.println(path);
File folder = new File(path);
if (!folder.exists()) {
folder.mkdirs();
}
String oldName = file.getOriginalFilename();
String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
//将文件写入到指定的目录中
file.transferTo(new File(folder, newName));
System.out.println("getScheme:" + request.getScheme());
System.out.println("getServerName:" + request.getServerName());
System.out.println("getServerPort" + request.getServerPort());
//页面回显数据
Map<String, String> result = new HashMap<>(16);
result.put("contentType", file.getContentType());
result.put("fileName", file.getOriginalFilename());
result.put("fileSize", file.getSize() + "");
return result;
}
}
知识点:HashMap(int initialCapacity)
hashMap源码中initialCapacity的初始值为16,负载因子为0.75;
所以一个hashMap中默认存储长度为16 * 0.75 = 12,也就是如果hashMap.put的键值对数量小于12的时候,hashMap位置够用;但是当添加的键值对数超过12后,hashMap需要扩容,一倍,也就是长度从12扩容到24;
例如键值对一共13个,这样剩余11个位置性能都浪费了,那么如果已知需要添加的键值对数量,就可以通过设置initialMap的值,来避免hashMap扩容,减少性能消耗。
eg:我们需要往hashMap中添加6个键值对,6 / 0.75 = 8;那就可以把initialCapacity设置为9比较合适,节省性能。
三、多文件上传
index.html
<form action="/uploads" method="post" enctype="multipart/form-data">
<input type="file" name="files" multiple>
<input type="submit" value="提交">
</form>
FileUploadController:
@PostMapping("/uploads")
public String uploads(@RequestParam("files") MultipartFile[] files, HttpServletRequest request) throws IOException {
//设置存储位置
String format = sdf.format(new Date());
String path = "D:\\flv\\" + format;
System.out.println(path);
File folder = new File(path);
if (!folder.exists()) {
folder.mkdirs();
}
for (MultipartFile file : files) {
String oldName = file.getOriginalFilename();
String newName = UUID.randomUUID().toString() + oldName.substring(oldName.lastIndexOf("."));
//将文件写入到指定的目录中
file.transferTo(new File(folder, newName));
String filePath = path + "\\" + newName;
System.out.println(filePath);
}
return "success";
}
四、Ajax 实现文件上传
主要是请求你页面的改变,对于
<!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="uploadFile()">
<script>
function uploadFile() {
var file = $("#file")[0].files[0];
var formData = new FormData();
formData.append("file", file);
$.ajax({
type:'post',
url:'/upload',
processData:false,
contentType:false,
data:formData,
success:function (msg) {
$("#result").html(msg);
}
})
}
</script>
</body>
</html>
知识点:Ajax 属性
processData:处理数据
默认情况下,processData 的值是 true,其代表以对象的形式上传的数据都会被转换为字符串的形式上传。而当上传文件的时候,则不需要把其转换为字符串,因此要改成false
contentType:发送数据的格式
和 contentType 有个类似的属性是 dataType , 代表的是期望从后端收到的数据的格式,一般会有 json 、text……等而 contentType 则是与 dataType 相对应的,其代表的是前端发送数据的格式,默认值:application/x-www-form-urlencoded
,代表的是 ajax 的 data 是以字符串的形式 如 id=2019&password=123456 使用这种传数据的格式,无法传输复杂的数据,比如多维数组、文件等
url:请求路径
data:请求参数
callback:回调函数
type:响应结果的类型
有时候要注意,自己所传输的数据格式和ajax的contentType格式是否一致,如果不一致就要想办法对数据进行转换
把contentType 改成 false 就会改掉之前默认的数据格式,在上传文件时就不会报错了。
五、属性配置
默认情况下 Spring Boot 无需做任何配置也能实现文件上传的功能,但有可能因默认配置不符而导致文件上传失败问题,
所以也可以按照对应的情况在 application.properties
中设置对应的属性;
# 上传文件的临时目录 (一般情况下不用特意修改)
spring.servlet.multipart.location=
# 上传文件最大为 1M (默认值 1M 根据自身业务自行控制即可)
spring.servlet.multipart.max-file-size=1048576
# 判断是否要延迟解析文件(相当于懒加载,一般情况下不用特意修改)
spring.servlet.multipart.resolve-lazily=false
# 禁用 thymeleaf 缓存
spring.thymeleaf.cache=false
# 是否支持批量上传 (默认值 true)
spring.servlet.multipart.enabled=true
# 上传请求最大为 10M(默认值10M 根据自身业务自行控制即可)
spring.servlet.multipart.max-request-size=10485760
# 文件大小阈值,当大于这个阈值时将写入到磁盘,否则存在内存中,(默认值0 一般情况下不用特意修改)
spring.servlet.multipart.file-size-threshold=0