参考资料:
1.SpringMVC上传文件的 4 种方式,你都会么?| SpringMVC第6篇
2.https://blog.csdn.net/justry_deng/article/details/80972817/
3.springboot实现本地存储文件上传及提供http访问服务
需求: 上传文件分别存到两个List中,两个List和json数据同时提交到后端
⏹前端HTML
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Titletitle>
head>
<body>
<h1>文件上传h1>
文件上传1<input class="fileTest1" type="file">
文件上传2<input class="fileTest1" type="file">
文件上传3<input class="fileTest1" type="file">
<hr>
文件上传11<input class="fileTest2" type="file">
文件上传22<input class="fileTest2" type="file">
文件上传33<input class="fileTest2" type="file">
<hr>
<button id="btn">文件上传button>
body>
<script th:src="@{js/jquery.min.js}">script>
<script>
// 点击发送Ajax请求
$('#btn').on('click', function () {
// 构建一个FormData对象
var formData = new FormData();
// 获取上传的所有文件,并进行遍历
$(".fileTest1").each(function () {
// this代表上传的每一个文件
const file1List = this.files[0];
if (!!file1List) {
formData.append("files1", file1List);
}
});
// files1这个key中同时存储着文件和字符串
formData.append("files1", "testString");
$(".fileTest2").each(function () {
// this代表上传的每一个文件
const file2List = this.files[0];
if (!!file2List) {
formData.append("files2", file2List);
}
});
// 将对象序列化为字符串传到后端
// 要发送的参数
const params1 = {
name: 'wangwu',
age: 30,
card: ["abc", "bbc"]
};
formData.append("jsonData1", JSON.stringify(params1));
formData.append("jsonData1", 1);
formData.append("jsonData1", "测试信息");
formData.append("jsonData1", ["名字", "年龄", "住址"]);
const params2 = {
name: 'zhaoliu',
age: 20
};
formData.append("jsonData2", JSON.stringify(params2));
$.ajax({
// 请求地址
url: '/wjec/groupFileUpload2',
type: "post",
// 因为我们要同时将json和文件数据同时提交到后端,所以需要使用FormData这个对象
// 该对象可以同时存储json和文件二进制流数据
data: formData,
/*
jQuery的ajax()方法发送的数据默认是序列化后的字符串,因此processData的值默认为true
我们要同时传输文件和表单数据,所以将contentType设置为false,告诉jQuery不要将要发送的数据处理为字符串
*/
processData: false,
// 告诉jQuery不要去设置Content-Type请求头
// FormDate对象是XMLHttpRquest2的类型,利用XHR对象发送FormDate生成的数据时,可以直接发送,不需要设置头部,
// XHR对象能够会自动识别数据类型是FormDate的实例,并配置相关的头部.
contentType: false,
// 请求成功以后函数被调用
success: function (response) {
// response为服务器端返回的数据,方法内部会自动将json字符串转换为json对象
console.log(response);
}
})
});
script>
html>
@PostMapping("/groupFileUpload")
@ResponseBody
public String groupFileUpload(MultipartFile[] files1, MultipartFile[] files2, String jsonData1, String jsonData2){
System.out.println(jsonData1);
System.out.println(jsonData2);
List<MultipartFile> multipartFiles1 = Arrays.asList(files1);
List<MultipartFile> multipartFiles2 = Arrays.asList(files2);
return "groupFileUpload";
}
通过MultipartHttpServletRequest接口来处理文件上传
1、springmvc 接受到上传文件的的请求之后,会将请求转换为 MultipartHttpServletRequest 类型的对象
2、MultipartHttpServletRequest 中提供了一系列方法来获取请求中的所有参数信息
3、其中 getParameterMap()用来获取非文件类型的参数列表
4、getMultiFileMap()方法用来获取上传的文件列表
@PostMapping("/groupFileUpload1")
@ResponseBody
public String groupFileUpload1(MultipartHttpServletRequest request){
Map<String, String[]> parameterMap = request.getParameterMap();
// 前端放到jsonData1key中的value会以数组的方式进行存储
String[] params = parameterMap.get("jsonData1");
System.out.println(Arrays.toString(params));
String[] params2 = parameterMap.get("jsonData2");
System.out.println(Arrays.toString(params2));
// 在书写js的时候,files1同时存储着文件和json信息,通过这种方式可以将json信息获取出来
String[] files1 = parameterMap.get("files1");
System.out.println(Arrays.toString(files1));
// 获取前端传入后端的文件
MultiValueMap<String, MultipartFile> multiFileMap = request.getMultiFileMap();
List<MultipartFile> multipartFiles1 = multiFileMap.get("files1");
List<MultipartFile> multipartFiles2 = multiFileMap.get("files2");
return "groupFileUpload";
}
自定义一个实体类
import org.springframework.web.multipart.MultipartFile;
import java.util.List;
public class FileUploadEntity {
private String[] jsonData1;
private String[] jsonData2;
private List<MultipartFile> files1;
private List<MultipartFile> files2;
// ...省略get和set方法
}
通过实体类的方式接收
@PostMapping("/groupFileUpload2")
@ResponseBody
public String groupFileUpload2(FileUploadEntity entity){
String[] jsonData1 = entity.getJsonData1();
System.out.println(Arrays.toString(jsonData1));
String[] jsonData2 = entity.getJsonData2();
System.out.println(Arrays.toString(jsonData2));
List<MultipartFile> files1 = entity.getFiles1();
List<MultipartFile> files2 = entity.getFiles2();
return "groupFileUpload";
}
配置文件
# 端口号设置
server.port: 8082
# 应用程序的上下文设置
server.servlet.context-path: /wjec
#上传文件的最大限制
spring.servlet.multipart.max-file-size = 300MB
spring.servlet.multipart.max-request-size = 900MB
# 关闭模板的缓存,默认是开启的
spring.thymeleaf.cache=false
# 自定义保存文件的位置
web.upload-path: D:/data/
#除了带上Spring Boot默认的静态资源路径之外,加上file:${web.upload-path}指向外部的文件资源上传路径。该路径下的静态资源可以直接对外提供HTTP访问服务。
#spring.resources.static-locations的方式已经过时,现在需要通过下面的配置方式指定
spring.web.resources.static-locations= classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:${web.upload-path}
后端处理
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.util.UriComponentsBuilder;
@Controller
public class FileUploadController {
// 绑定文件上传路径到uploadPath
@Value("${web.upload-path}")
private String uploadPath;
// 注入上下文对象的url
@Value("${server.servlet.context-path}")
private String contextPath;
private SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd/");
@PostMapping("/groupFileUpload1")
@ResponseBody
public String groupFileUpload1(MultipartHttpServletRequest request){
// 通过日期对上传的文件归类保存
String format = sdf.format(new Date());
File folder = new File(uploadPath + format);
if (!folder.isDirectory()) {
folder.mkdirs();
}
// 获取前端上传的文件
MultiValueMap<String, MultipartFile> multiFileMap = request.getMultiFileMap();
// 存储静态资源访问url的List
ArrayList<String> urlList = new ArrayList<>();
// 获取files1为key的上传文件列表
List<MultipartFile> multipartFiles1 = multiFileMap.get("files1");
try {
for (MultipartFile multipartFile: multipartFiles1){
// 对上传的文件重命名,避免文件重名
String oldName = multipartFile.getOriginalFilename();
String newName = UUID.randomUUID().toString()
+ oldName.substring(oldName.lastIndexOf("."), oldName.length());
// 文件保存
multipartFile.transferTo(new File(folder, newName));
// 通过工具类构造静态资源访问url
UriComponentsBuilder uriComponentsBuilder = UriComponentsBuilder.newInstance();
uriComponentsBuilder
.scheme(request.getScheme())
.host(request.getServerName())
.port(request.getServerPort())
.path(contextPath + "/")
.path(format + newName)
.build();
urlList.add(uriComponentsBuilder.toUriString());
}
} catch (IOException e) {
System.out.println(e);
}
// 打印存储到本地磁盘资源的访问url
System.out.println(urlList.toString());
return "";
}
}