<!-- https://mvnrepository.com/artifact/commons-fileupload/commons-fileupload -->
>
>commons-fileupload >
>commons-fileupload >
>1.4 >
>
<!-- hutool-all -->
>
>cn.hutool >
>hutool-all >
>5.3.9 >
>
修改为自己需要的大小
#文件上传大小配置
spring:
servlet:
multipart:
max-file-size: 1024MB
max-request-size: 1024MB
#文件上传根目录
file:
path: /Users/tianpuyang/uploadPath/file/
uploadFile:文件上传接口
支持多文件上传,url会以逗号分割的形式返回
uploadStatus:上传进度获取接口
通过前端循环调用获取上传进度
deleteFile:文件删除接口
传入uploadFile接口生成的url即可删除
@RestController
public class FileUploadController {
private final Log log = LogFactory.get();
/**
* 配置的上传路径
*/
@Value("${file.path}")
private String filePath;
/**
* 普通文件上传
*
* @param files
* @param request
* @return
*/
@PostMapping("/uploadFile")
@ApiOperation("普通文件上传")
public JsonResult uploadFile(@RequestParam("files") List<CommonsMultipartFile> files, HttpServletRequest request) {
StringBuffer buffer = new StringBuffer();
for (CommonsMultipartFile file : files) {
//获取原文件名称和后缀
String originalFilename = file.getOriginalFilename();
// 获取文件后缀名
String fil_extension = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
LocalDateTime now = LocalDateTimeUtil.now();
int year = now.getYear();
int month = now.getMonthValue();
int day = now.getDayOfMonth();
long milli = now.toInstant(ZoneOffset.of("+8")).toEpochMilli();
String path = StrUtil.format("{}/{}/{}/{}", year, month, day, milli + originalFilename);
try {
File file1 = new File(filePath + path);
boolean mkdirs = file1.mkdirs();
log.info("文件夹{}创建{}", file1.getAbsolutePath(), mkdirs ? "成功" : "失败");
file.transferTo(file1);
log.info("{} 上传成功!", originalFilename);
if (StrUtil.isBlank(buffer)) {
path = StrUtil.format("{}://{}:{}/{}/{}", request.getScheme(), StrUtil.equals(SystemUtil.getHostInfo().getAddress(), "127.0.0.1") ? "192.168.31.120" : SystemUtil.getHostInfo().getAddress(), request.getServerPort(), "upload", path);
} else {
path = StrUtil.format(",{}://{}:{}/{}/{}", request.getScheme(), StrUtil.equals(SystemUtil.getHostInfo().getAddress(), "127.0.0.1") ? "192.168.31.120" : SystemUtil.getHostInfo().getAddress(), request.getServerPort(), "upload", path);
}
buffer.append(path);
} catch (IOException e) {
e.printStackTrace();
log.error("{} 上传失败!", originalFilename);
continue;
}
}
return new JsonResult(buffer);
}
/**
* 获取上传进度
*
* @param request
* @return
*/
@GetMapping(value = "/uploadStatus")
@ApiOperation("获取上传进度")
public JsonResult uploadStatus(HttpServletRequest request) {
HttpSession session = request.getSession();
ProgressEntity percent = (ProgressEntity) session.getAttribute("status");
return new JsonResult(percent);
}
/**
* 删除文件
*
* @param url http://127.0.0.1:8080/upload/2020/7/19/1595158527436video.mp4
* @return
*/
@GetMapping(value = "/deleteFile")
@ApiOperation("删除文件")
public JsonResult deleteFile(String url) {
//截取第四个“/”后面的字符串
int i1 = url.indexOf('/');
int i2 = url.indexOf('/', i1 + 1);
int i3 = url.indexOf('/', i2 + 1);
int i4 = url.indexOf("/", i3 + 1);
String substring = url.substring(i4 + 1, url.length());
String relPath = filePath + substring;
File file = new File(relPath);
if (file.isFile() && file.exists()) {
boolean delete = file.delete();
if (!delete) {
log.error("{} 删除失败!", substring);
throw new MyException(ErrorEnum.FILE_DELETE_EXCEPTION);
} else {
log.info("{} 删除成功!", substring);
}
} else {
log.error("{} 文件不存在!", substring);
throw new MyException(ErrorEnum.FILE_NOT_EXISTS);
}
return new JsonResult("删除成功");
}
}
@Component
@Data
@ToString
public class ProgressEntity {
// 读取的文件的比特数
private long pBytesRead = 0L;
// 文件的总大小
private long pContentLength = 0L;
// 目前正在读取第几个文件
private int pItems;
private long startTime = System.currentTimeMillis();
}
public class CustomMultipartResolver extends CommonsMultipartResolver {
@Autowired
private FileUploadProgressListener listener;
@Override
protected MultipartParsingResult parseRequest(HttpServletRequest request) throws MultipartException {
String encoding = determineEncoding(request);
FileUpload fileUpload = prepareFileUpload(encoding);
// 文件上传进度监听器设置session用于存储上传进度
listener.setHttpSession(request.getSession());
// 将文件上传进度监听器加入到 fileUpload 中
fileUpload.setProgressListener(listener);
try {
List<FileItem> fileItems = ((ServletFileUpload) fileUpload).parseRequest(request);
return parseFileItems(fileItems, encoding);
} catch (FileUploadBase.SizeLimitExceededException ex) {
throw new MaxUploadSizeExceededException(fileUpload.getSizeMax(), ex);
} catch (FileUploadBase.FileSizeLimitExceededException ex) {
throw new MaxUploadSizeExceededException(fileUpload.getFileSizeMax(), ex);
} catch (FileUploadException ex) {
throw new MultipartException("Failed to parse multipart servlet request", ex);
}
}
获取上传进度的解决方法是将进度放进session中
/**
* 文件上传进度
*/
@Component
public class FileUploadProgressListener implements ProgressListener {
private HttpSession httpSession;
public void setHttpSession(HttpSession httpSession) {
this.httpSession = httpSession;
ProgressEntity status = new ProgressEntity();
//默认进度为0
httpSession.setAttribute("status", status);
}
/**
* pBytesRead 到目前为止读取文件的比特数
* pContentLength 文件总大小
* pItems 目前正在读取第几个文件
*/
@Override
public void update(long pBytesRead, long pContentLength, int pItems) {
ProgressEntity status = (ProgressEntity) httpSession.getAttribute("status");
status.setPBytesRead(pBytesRead);
status.setPContentLength(pContentLength);
status.setPItems(pItems);
// System.out.println("UploadProgressListener update ProgressEntity: " + status.toString());
}
}
用来实现通过解析url访问资源
@Configuration
@EnableAutoConfiguration
public class FileConfig implements WebMvcConfigurer {
/**
* 指定自定义解析器
* 将 multipartResolver 指向我们刚刚创建好的继承 CustomMultipartResolver 类的 自定义文件上传处理类
*
* @return
*/
@Bean(name = "multipartResolver")
public MultipartResolver multipartResolver() {
return new CustomMultipartResolver();
}
/**
* 图片保存路径,自动从yml文件中获取数据
* 示例: D:/upload/
*/
@Value("${file.path}")
private String fileSavePath;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
/**
* 配置资源映射
* 意思是:如果访问的资源路径是以“/images/”开头的,
* 就给我映射到本机的“E:/images/”这个文件夹内,去找你要的资源
* 注意:E:/images/ 后面的 “/”一定要带上
*/
registry.addResourceHandler("/upload/**")
.addResourceLocations("file:"+fileSavePath);
}
}