文件上传原理
1. 文件上传的目的是实现资源共享。
2. 把用户电脑中的资源复制到服务器的过程称之为文件上传。
3. 底层是通过IO流实现的。
使用SpringBoot实现文件上传
- 搭建一个SpringBoot工程
- 准备一个页面文件上传的页面
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>文件上传</h1> <form action="/upload/file/" enctype="multipart/form-data" method="post"> <input type="file" name="file" type="text"> <input type="submit" value="提交文件"> </form> </body> </html>
配置文件
spring:
freemarker:
suffix: .html
cache: false
servlet:
multipart:
location: F://tmp
#修改临时文件夹
页面跳转的请求
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@Controller
public class PageController {
@RequestMapping("/upload")
public String upload(){
return "upload";
}
}
编写service层
package com.example.service;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;
@Service
public class UploadService {
/**
* 文件上传的底层原理是request.getInputStream()
* @param multipartFile springmvc提供的文件上传的包装类
* @return
*/
public String uploadImg(MultipartFile multipartFile) {
try {
String oldName = multipartFile.getOriginalFilename();
// 获取文件原来的名字
String suffix = oldName.substring(oldName.lastIndexOf("."));
// 获取文件后缀名
String newName = UUID.randomUUID()+suffix;
// 日期目录 做隔离 方便查找
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String datePath = dateFormat.format(new Date());
File file = new File("E://tmp//" + datePath+"//"+newName);
if(!file.exists())
file.mkdirs();
// 如果不存在则创建该目录
multipartFile.transferTo(file);
return "ok";
} catch (IOException e) {
e.printStackTrace();
return "fail";
}
}
}
编写controller层
import com.example.service.UploadService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
@Controller
public class UploadController {
@Autowired
UploadService uploadService;
/**
*
* @param multipartFile
* @param request
* @return
*/
@PostMapping("/upload/file")
@ResponseBody
public String upload(@RequestParam("file")MultipartFile multipartFile, HttpServletRequest request){
if(multipartFile.isEmpty()){
return "文件为空";
}
return uploadService.uploadImg(multipartFile);
}
}
测试!
在controller层打一个断点,点击debug按钮开始调试。
产生临时文件夹的好处时当用户出现网络异常或者刷新网页时传到一半的无效文件不会进入服务器文件夹而是进入临时文件夹,临时文件夹在上传完成后会自动删除文件。如果上传两个完全一样的文件名会直接覆盖。
优化
直接提交,不需要按提交按钮。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>文件上传</h1>
<form action="/upload/file/" enctype="multipart/form-data" method="post" id="uploadform">
<input type="file" name="file" type="text" onchange="onupload()" >
</form>
<script>
function onupload() {
document.getElementById("uploadform").submit();
}
</script>
</body>
</html>
前端可选择多个文件
<input type="file" name="file" multiple type="text" onchange="onupload()" >
目录资源映射
现在有一个问题就是上传上去的文件根目录时被写死的,我们无法在通过localhost:8080来自由访问上传的文件。这时候就需要一个资源映射机制。类似于static目录。
package com.example.config;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Value("${file.staticPath}")
private String staticPath;
@Value("${file.uploadFolder}")
private String uploadPath;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler(staticPath).addResourceLocations(uploadPath);
}
}
这样我们就可以通过配置文件来修改对应资源的映射了!
file:
staticPath: /imgs/**
uploadFolder: file:E:/tmp/