文件上传
SpringBoot中对文件上传做了简化,使文件上传变得非常方便,以下分享前后端分离的情况下单文件上传与多文件上传的写法。
-
依赖添加(pom.xml)(基本依赖)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
-
配置
Java中文件上传涉及2个组件,其一是基于commons-fileupload的CommonsMutipartResolver来处理multipart请求,其二是基于Servlet 3.0的StandardServletMultipartResolver来处理multipart请求。Tomcat7开始支持Servlet 3.0,所以SpringBoot内嵌了Tomcat,SpringBoot提供的文件上传自动化配置类MultipartAutoConfiguration,如果开发者未提供MultipartResolver,默认也采用StandardServletMultipartResolver组件,所以SpringBoot文件上传可以做到零配置。
-
application.properties配置(非必需)
#配置文件上传
#是否开启文件上传支持,默认true
spring.servlet.multipart.enabled=true
#文件写入磁盘的阈值,默认为0
spring.servlet.multipart.file-size-threshold=0
#上传文件的临时保存位置
spring.servlet.multipart.location=D:\\data
#上传的单个文件的最大大小,默认1MB
spring.servlet.multipart.max-file-size=100MB
#多文件上传时,文件的总大小,默认10MB
spring.servlet.multipart.max-request-size=100MB
#表示文件是否延迟解析,默认为false
spring.servlet.multipart.resolve-lazily=false
-
Controller
package cn.wsyjlly.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/**
* @author wsyjlly
* @create 2019.06.13 - 17:23
**/
@RestController
public class FileUploadController {
private String fomartDate = new SimpleDateFormat("yyyy-MM-dd").format(new Date());
private final String UPLOAD_PATH = "/uploadFiles/";
private final Integer SUCCESS = 1;
private final Integer FAILURE = 0;
private Logger logger = LoggerFactory.getLogger(getClass());
/*
* 单文件上传
* */
@PostMapping("/upload")
public ModelMap upload(MultipartFile uploadFile, HttpServletRequest request) {
ModelMap map = new ModelMap();
if (uploadFile == null){
map.addAttribute("status",FAILURE);
map.addAttribute("message","未选择文件");
return map;
}
File folder = getRootPath();
logger.debug("文件夹路径:"+folder.getAbsolutePath());
String originalFilename = uploadFile.getOriginalFilename();
logger.debug("文件原名:"+originalFilename);
String newName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."), originalFilename.length());
try {
uploadFile.transferTo(new File(folder,newName));
String filePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + UPLOAD_PATH + fomartDate+"/" + newName;
logger.debug("文件访问路径:"+filePath);
map.addAttribute("filePath",filePath);
map.addAttribute("status",SUCCESS);
return map;
} catch (IOException e) {
e.printStackTrace();
}
map.addAttribute("status",FAILURE);
return map;
}
/*
* 多文件上传
* */
@PostMapping("/uploads")
public ModelMap uploads(MultipartFile[] uploadFiles, HttpServletRequest request) {
ModelMap map = new ModelMap();
logger.debug("文件个数:"+uploadFiles.length);
//String realPath = ResourceUtils.getURL("classpath:").getPath()+UPLOAD_PATH;
File folder = getRootPath();
HashMap<String, Map> fileListUploadStatus = new HashMap<>();
for (MultipartFile file:uploadFiles){
HashMap<String, Object> item = new HashMap<>();
String originalFilename = file.getOriginalFilename();
System.out.println("————————————————————————————————");
logger.debug("————————————————————————————————");
logger.debug("文件原名:"+originalFilename);
logger.debug("文件大小:"+file.getSize());
logger.debug("文件类型:"+file.getContentType());
String newName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."), originalFilename.length());
try {
file.transferTo(new File(folder,newName));
String filePath = request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort() + UPLOAD_PATH + fomartDate+"/" + newName;
logger.debug("访问地址:"+filePath);
logger.debug("地址文件名:"+newName);
item.put("isUpload",true);
item.put("url",filePath);
fileListUploadStatus.put(originalFilename,item);
} catch (IOException e) {
item.put("isUpload",false);
item.put("url","");
fileListUploadStatus.put(originalFilename,item);
e.printStackTrace();
}
}
map.addAttribute("resultList",fileListUploadStatus);
return map;
}
private File getRootPath(){
File file = new File(System.getProperty("user.dir")+UPLOAD_PATH);
if(!file.exists()){//如果文件夹不存在
file.mkdirs();//创建文件夹
}
String rootPath = file.getAbsolutePath();
File folder = new File(rootPath+'/' + fomartDate);
if (!folder.isDirectory()){
folder.mkdirs();
}
return folder;
}
}
-
静态资源访问路径配置
如果上传资源需要被访问,则须配置上传文件路径添加静态资源访问路径。
注意:在Linux系统和window系统中相对于当前运行位置的盘的根路径都可表示为 ‘/’
静态资源文件路径分为两种:
- 相对路径(相对于classes的路径)即:'classpath:'
- 绝对路径:文件系统路径,配置文件系统静态资源路径时须添加前缀:'file:'
/**
* @author wsyjlly
* @create 2019.06.12 - 16:17
**/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
private Logger logger = LoggerFactory.getLogger(getClass());
/*
* 配置静态资源过滤策略
* 将静态资源路径映射为访问路径
* */
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/static/**")
.addResourceLocations("classpath:/");
String uploadPath = new File(System.getProperty("user.dir"),"uploadFiles")
.getAbsolutePath().replaceAll("\\\\","/")+"/";
registry.addResourceHandler("/uploadFiles/**").
addResourceLocations("file:"+uploadPath);
logger.info("上传文件路径映射:/uploadFiles/** ————>> "+uploadPath);
}
}