1.本篇概要
文件上传在日常开发过程中比较常见的功能之一,SpringBoot中并没有提供额外的文件上传技术,还是依赖于SpringMVC的文件上传技术。我们要实现文件上传不需要引入其他依赖,spring-boot-starter-web中依赖的Spring框架已经给我们提供了相关功能。
2.MultipartFile
2.1 MultipartFile简介
在SpringMVC中提供了MultipartFile这个封装类,它包含了文件的二进制流和文件相关属性(文件名、大小等),而在Spring Boot中也是使用此封装类进行文件上传。
MultipartFile是个接口,它的实现类有CommonsMultipartFile和StandardMultipartFile,这里做一下简单说明:
- CommonsMultipartFile: 是基于apache fileupload的解析;
- StandardMultipartFile: 是基于j2ee自带的文件上传进行解析,也就是使用Servlet3.0提供的javax.servlet.http.Part上传方式。
正常使用MultipartFile时,无需关心底层是以哪种方式进行文件上传处理的,SpringMVC会给我们做相应的转换。
另外要注意的是,如果想要实现文件上传,必须将表单的method设置为post,并将enctype设置为multipart/form-data。只有这样,浏览器才会把所选择文件的二进制数据发送给服务器。SpringMVC在文件上传时,会将上传的文件映射为MultipartFile对象,并对MultipartFile对象进行文件的解析和保存。
2.2 MultipartFile内的API方法
public interface MultipartFile extends InputStreamSource {
//文件的接收参数 @RequestParam MultipartFile file 中的 file
String getName();
//获取上传文件的原名称;
@Nullable
String getOriginalFilename();
//获取文件MIME类型,如application/pdf、image/pdf等;
@Nullable
String getContentType();
//是否上传的文件是否为空;
boolean isEmpty();
//获取文件的字节大小,单位为byte;
long getSize();
//获取文件数据
byte[] getBytes() throws IOException;
//获取文件流;
@Override
InputStream getInputStream() throws IOException;
//获得一个MultipartFile对象
default Resource getResource() {
return new MultipartFileResource(this);
}
//将上传的文件保存到目标文件中
void transferTo(File dest) throws IOException, IllegalStateException;
//将接收到的文件传输到给定的目标文件
default void transferTo(Path dest) throws IOException, IllegalStateException {
FileCopyUtils.copy(getInputStream(), Files.newOutputStream(dest));
}
}
3. 单文件上传
3.1 表单提交
添加相关依赖包
主要是web依赖和thymeleaf模板依赖。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-json</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2-extension</artifactId>
<version>2.0.4</version>
</dependency>
<!--thymeleaf模板引擎 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
编写文件上传页面toUpload.html
<!DOCTYPE HTML>
<html>
<head>
<title>upload page</title>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
</head>
<body>
<form enctype="multipart/form-data" method="post" action="/upload">
文件: <input type="file" name="fileUpload"/>
<input type="submit" value="上传"/>
</form>
</body>
</html>
编写配置application.yml
server:
port: 8080
spring:
servlet:
multipart:
enabled: true #是否支持批量上传
max-file-size: 10MB #上传文件最大为 10M
max-request-size: 100MB #上传请求最大为 100M
thymeleaf:
cache: false
创建文件上传的UploadController类
@Controller
public class FileUploadController {
@RequestMapping("/toUpload")
public String toUpload(){
return "toUpload";
}
@ResponseBody
@PostMapping("/upload")
public Object upload(MultipartFile fileUpload){
Map<String,Object> resultMap = new HashMap<>(8);
//获取文件名
String fileName = fileUpload.getOriginalFilename();
//获取文件后缀名
String suffixName = Objects.requireNonNull(fileName).substring(fileName.lastIndexOf("."));
//重新生成文件名
fileName = UUID.randomUUID() + suffixName;
//指定本地文件夹存储图片
try {
String filePath = "E:\\file\\";
File dir = new File(filePath);
if (!dir.exists()) {
dir.mkdirs();
}
File uploadFile = new File(filePath + fileName);
fileUpload.transferTo(uploadFile);
resultMap.put("msg","upload success");
resultMap.put("code","10000");
return resultMap;
} catch (Exception e) {
e.printStackTrace();
resultMap.put("msg","upload failed");
resultMap.put("code","10001");
return resultMap;
}
}
}
测试结果如下
3.2 ajax方式提交
其他同3.1,增加页面以及Controller对应方法
@RequestMapping("/toUpload2")
public String toUpload2(){
return "toUpload2";
}
编写文件上传页面toUpload2.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
</head>
<body>
<div id="result"></div>
<input type="file" id="file">
<input type="button" value="upload" onclick="fileUpload();">
<script>
function fileUpload() {
let file = $("#file")[0].files[0];
let formData = new FormData();
formData.append("file",file);
$.ajax({
url:'/upload',
type:'post',
processData:false,
contentType:false,
data:formData,
success:function (data) {
$("#result").html(data.msg);
}
});
}
</script>
</body>
</html>
测试结果如下
4. 多文件上传
多文件上传其实把Controller中的MultipartFile改成数组即可
@Controller
public class MultiFileUploadController {
@RequestMapping("/toMultiUpload")
public String toMultiUpload(){
return "toMultiUpload";
}
@ResponseBody
@PostMapping("/upload2")
public Object upload(MultipartFile[] files){
Map<String,Object> resultMap = new HashMap<>(8);
String filePath = "E:\\file\\";
File dir = new File(filePath);
if (!dir.exists()) {
dir.mkdirs();
}
for(MultipartFile file: files){
//获取文件名
String fileName = file.getOriginalFilename();
//获取文件后缀名
String suffixName = Objects.requireNonNull(fileName).substring(fileName.lastIndexOf("."));
//重新生成文件名
fileName = UUID.randomUUID() + suffixName;
File uploadFile = new File(filePath + fileName);
try {
file.transferTo(uploadFile);
resultMap.put("msg","upload success");
resultMap.put("code","10000");
} catch (IOException e) {
e.printStackTrace();
resultMap.put("msg","upload failed");
resultMap.put("code","10001");
}
}
return resultMap;
}
}
前端页面表单中添加multiple属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>multi upload</title>
</head>
<body>
<form action="upload2" method="post" enctype="multipart/form-data">
<input type="file" name="files" multiple>
<input type="submit" value="Upload">
</form>
</body>
</html>
测试结果如下
本文暂时没有评论,来添加一个吧(●'◡'●)