minio 是一个基于 Apache License v2.0 开源协议的对象存储服务。非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小。 是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。
如果不考虑文件存储上云,minio 是一个非常不错的选择,并且支持分布式部署。
// 引入mioio的依赖包
<!-- minio -->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>7.1.4</version>
</dependency>
// controller层
@PostMapping(value = "/uploadFile", headers = "content-type=multipart/form-data")
public Response<List<FileReturn>> uploadFiles(List<MultipartFile> fileList) {
return fileService.uploadFileList(fileList);
}
// service层 --- 伪代码
public List<FileReturn> uploadFileList(List<MultipartFile> fileList) {
// 参数校验
if (CollectionUtils.isEmpty(fileList)) {
// throw new Exception
}
List<FileVO> fileVOList = new ArrayList<>();
List<FileReturn> fileReturnList = new ArrayList<>();
// String userId = xxxx;
for (MultipartFile file : fileList) {
// 校验文件 todo
// 开始上传
try {
// 将文件存入minio
Map<String, String> fileMap = minioClient.putObject(file);
// 创建文件对象,设置属性
FileVO fileVO = new FileVO()
.init(userId)
.setFileType(suffix)
.setFileOldName(Base64.decodeStr(fileMap.get(FileModel.OLD_NAME), "UTF-8"))
.setFileName(fileMap.get(FileModel.NAME))
.setFilePath(fileMap.get(FileModel.NAME))
.setFileNetPath(fileMap.get(FileModel.URL))
.setFileSize(new BigDecimal(fileMap.get(FileModel.SIZE)))
.setFileUploadUser(userId)
.setFileUploadTime(LocalDateTime.now());
fileVO.setId(IdWorker.getId());
fileVOList.add(fileVO);
// 返回文件id,文件url,文件名
FileReturn fileReturn = new FileReturn().setFileId(fileVO.getId()).setFileNetPath(fileVO.getFileNetPath()).setFileAbsolutePath(this.preview(fileVO.getFileNetPath())).setFileOldName(fileVO.getFileOldName());
fileReturnList.add(fileReturn);
} catch (Exception e) {
// 删除minio中已经保存的文件
if (fileReturnList.size() > 0) {
fileReturnList.forEach(vo -> minioClient.removeObject(vo.getFileNetPath()));
}
log.info("上传文件异常", e);
// throw new Exception
}
}
// 保存附件信息到数据库 持久化
mapper.saveList(fileVOList);
return fileReturnList;
}
// service层
// 文件下载前端传入文件id --- 伪代码
public void downloadFile(String fileId, HttpServletResponse response) {
FileVO contractFile = mapper.selectById(fileId);
if (!Objects.isNull(contractFile)) {
try {
response.setHeader("Content-Disposition", "attachment;filename=" + contractFile.getFileName());
minioClient.getObject(contractFile.getFilePath(), response.getOutputStream());
// 持久化:记录下载次数,根据业务来处理
// ...
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
// service层 --- 伪代码
public String removeFile(String fileId, HttpServletResponse response) {
FileVO contractFile = mapper.selectById(fileId);
if (!Objects.isNull(contractFile)) {
try {
response.setHeader("Content-Disposition", "attachment;filename=" + contractFile.getFileName());
// 删除minio文件
minioClient.removeFile(contractFile.getFilePath());
// 删除数据库文件 持久化操作
// ...
} catch (IOException e) {
// return "删除失败";
}
}
return "删除成功";
}
// service层 --- 伪代码
// 返回文件的url全路径即可
public String preview(String filePath) {
String url = "";
if (StringUtils.isNotEmpty(filePath)) {
int index = filePath.indexOf('/');
String objectName = filePath.substring(index + 1);
url = minioClient.getObjectUrl(objectName, 24 * 3600, Method.GET);
}
return url;
}
public String getObjectUrl(String objectName, Integer expires, Method method) {
try {
if (expires >= 1 && expires <= 604800) {
if (method == null) {
method = Method.GET;
}
return minioClient.getPresignedObjectUrl((GetPresignedObjectUrlArgs)((io.minio.GetPresignedObjectUrlArgs.Builder)((io.minio.GetPresignedObjectUrlArgs.Builder)GetPresignedObjectUrlArgs.builder().method(method).bucket(minioConfig.getBucket())).object(objectName)).expiry(expires, TimeUnit.SECONDS).build());
} else {
throw new InvalidExpiresRangeException(expires, "expires must be in range of 1 to 604800");
}
} catch (Throwable var6) {
throw new BusinessException(FILE_LOAD_EXCEPTION.getCode(), FILE_LOAD_EXCEPTION.getMessage(), var6.getMessage());
}
}