SpringBoot基础教程2-1-10 文件上传
程序员文章站
2022-03-11 22:13:24
...
1. 概述
文件上传,下载功能是web
中常见功能,SpringBoot
几乎把文件上传功能封装到了极致,只需短短的配置,和几行代码就能实现文件上传功能。
2. 源码分析
2.1. 添加pom.xml
依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
2.2 配置文件application.yml
spring:
thymeleaf:
# 禁用 thymeleaf 缓存
cache: false
servlet:
multipart:
# 是否支持批量上传 (默认值 true)
enabled: true
# 上传文件的临时目录 (一般情况下不用特意修改)
location:
# 上传文件最大为 10M (默认值 1M 根据自身业务自行控制即可)
max-file-size: 10MB
# 上传请求最大为 10M(默认值10M 根据自身业务自行控制即可)
max-request-size: 10MB
# 文件大小阈值,当大于这个阈值时将写入到磁盘,否则存在内存中,(默认值0 一般情况下不用特意修改)
file-size-threshold: 0
# 判断是否要延迟解析文件(相当于懒加载,一般情况下不用特意修改)
resolve-lazily: false
默认情况上面配置可以直接省略,不过了解配置能让我们更加理解
SpringBoot
文件上传细节,方便定位问题
2.3 Controller
层
@Slf4j
@Controller
@RequestMapping
public class FileUploadController {
@GetMapping("/index")
public String index() {
return "index";
}
@PostMapping("/uploadOne")
@ResponseBody
public Map<String, String> uploadOne(@RequestParam("file") MultipartFile file) throws IOException {
// TODO 将文件写入到指定目录(具体开发中有可能是将文件写入到云存储/或者指定目录通过 Nginx 进行 gzip 压缩和反向代理,此处只是为了演示故将地址写成本地电脑指定目录)
file.transferTo(new File("E:\\temp\\" + file.getOriginalFilename()));
Map<String, String> result = new HashMap<>(16);
result.put("contentType", file.getContentType());
result.put("fileName", file.getOriginalFilename());
result.put("fileSize", file.getSize() + "");
return result;
}
@PostMapping("/uploadMulti")
@ResponseBody
public List<Map<String, String>> uploadMulti(@RequestParam("file") MultipartFile[] files) throws IOException {
if (files == null || files.length == 0) {
return null;
}
List<Map<String, String>> results = new ArrayList<>();
for (MultipartFile file : files) {
// TODO
file.transferTo(new File("E:\\temp\\" + file.getOriginalFilename()));
Map<String, String> map = new HashMap<>(16);
map.put("contentType", file.getContentType());
map.put("fileName", file.getOriginalFilename());
map.put("fileSize", file.getSize() + "");
results.add(map);
}
return results;
}
@PostMapping("/uploadBase")
@ResponseBody
public Map<String, String> uploadBase(String base64) throws IOException {
// TODO BASE64 方式的 格式和名字需要自己控制(如 png 图片编码后前缀就会是 data:image/png;base64,)
final File tempFile = new File("E:\\temp\\test.jpg");
// TODO 防止有的传了 data:image/png;base64, 有的没传的情况
String[] d = base64.split("base64,");
final byte[] bytes = Base64Utils.decodeFromString(d.length > 1 ? d[1] : d[0]);
FileCopyUtils.copy(bytes, tempFile);
Map<String, String> result = new HashMap<>(16);
result.put("contentType", tempFile.getAbsolutePath());
result.put("fileName", tempFile.getName());
result.put("fileSize", String.valueOf(tempFile.getTotalSpace()));
return result;
}
}
@GetMapping("/index")
用来跳转到index.html
@PostMapping("/uploadOne")
,@PostMapping("/uploadMulti")
,@PostMapping("/uploadBase")
分别处理单个文件,多个文件,BASE64编码@RequestParam("file")
此处的ile
对应的就是html
中name="file"
的input
标签,而将文件真正写入的还是借助的commons-io
中的FileUtils.copyInputStreamToFile(inputStream,file)
2.4 上传交互页面
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<body>
<h2>单一文件上传示例</h2>
<div>
<form method="POST" enctype="multipart/form-data" action="/uploadOne">
<p>
文件1:<input type="file" name="file"/>
<input type="submit" value="上传"/>
</p>
</form>
</div>
<hr/>
<h2>批量文件上传示例</h2>
<div>
<form method="POST" enctype="multipart/form-data"
action="/uploadMulti">
<p>
文件1:<input type="file" name="file"/>
</p>
<p>
文件2:<input type="file" name="file"/>
</p>
<p>
<input type="submit" value="上传"/>
</p>
</form>
</div>
<hr/>
<h2>Base64文件上传</h2>
<div>
<form method="POST" action="/uploadBase">
<p>
BASE64编码:<textarea name="base64" rows="10" cols="80"></textarea>
<input type="submit" value="上传"/>
</p>
</form>
</div>
</body>
</html>
3. 测试结果
其中,
BASE64
测试,先将一张图片转换为BASE64
编码
4. 工程目录
5. 结束语
说点什么呢,有任何建议,欢迎留言探讨,本文源码。
欢迎关注博主公众号,第一时间推送最新文章