|
|
|
@ -3,21 +3,20 @@ package com.gccloud.dataroom.core.module.file.service.impl;
|
|
|
|
|
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
|
|
|
|
|
import com.gccloud.common.exception.GlobalException;
|
|
|
|
|
import com.gccloud.dataroom.core.config.DataRoomConfig;
|
|
|
|
|
import com.gccloud.dataroom.core.config.MinioConfig;
|
|
|
|
|
import com.gccloud.dataroom.core.config.bean.FileConfig;
|
|
|
|
|
import com.gccloud.dataroom.core.config.bean.MinioConfig;
|
|
|
|
|
import com.gccloud.dataroom.core.module.file.entity.DataRoomFileEntity;
|
|
|
|
|
import com.gccloud.dataroom.core.module.file.service.FileOperationStrategy;
|
|
|
|
|
import com.gccloud.dataroom.core.module.file.service.IDataRoomFileService;
|
|
|
|
|
import com.gccloud.dataroom.core.module.file.service.IDataRoomOssService;
|
|
|
|
|
import com.gccloud.dataroom.core.utils.MinioFileInterface;
|
|
|
|
|
import io.minio.MinioClient;
|
|
|
|
|
import io.minio.PutObjectArgs;
|
|
|
|
|
import lombok.SneakyThrows;
|
|
|
|
|
import com.gccloud.dataroom.core.utils.PathUtils;
|
|
|
|
|
import io.minio.*;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.apache.commons.io.FilenameUtils;
|
|
|
|
|
import org.apache.commons.io.IOUtils;
|
|
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
import org.springframework.context.annotation.Conditional;
|
|
|
|
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
|
|
|
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
|
|
|
|
import org.springframework.http.HttpStatus;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
@ -26,6 +25,7 @@ import javax.annotation.Resource;
|
|
|
|
|
import javax.servlet.http.HttpServletRequest;
|
|
|
|
|
import javax.servlet.http.HttpServletResponse;
|
|
|
|
|
import java.io.InputStream;
|
|
|
|
|
import java.io.UnsupportedEncodingException;
|
|
|
|
|
import java.net.URLEncoder;
|
|
|
|
|
import java.time.LocalDate;
|
|
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
@ -35,14 +35,11 @@ import java.time.format.DateTimeFormatter;
|
|
|
|
|
*
|
|
|
|
|
* @author Acechengui
|
|
|
|
|
*/
|
|
|
|
|
@Service("minioFileService")
|
|
|
|
|
@Conditional(FileOperationStrategy.MinioFileCondition.class)
|
|
|
|
|
@Slf4j
|
|
|
|
|
@Service
|
|
|
|
|
@ConditionalOnProperty(prefix = "gc.starter.file", name = "type", havingValue = "minio")
|
|
|
|
|
public class DataRoomMinioServiceImpl implements IDataRoomOssService {
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
private MinioConfig minioConfig;
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
private MinioClient minioclient;
|
|
|
|
|
|
|
|
|
@ -51,14 +48,13 @@ public class DataRoomMinioServiceImpl implements IDataRoomOssService {
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
private IDataRoomFileService sysFileService;
|
|
|
|
|
|
|
|
|
|
@Resource
|
|
|
|
|
private MinioFileInterface minioFileInterface;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 上传文件
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
@SneakyThrows
|
|
|
|
|
@Override
|
|
|
|
|
public DataRoomFileEntity upload(MultipartFile file, DataRoomFileEntity fileEntity, HttpServletResponse response, HttpServletRequest request) {
|
|
|
|
|
String originalFilename = file.getOriginalFilename();
|
|
|
|
@ -66,7 +62,7 @@ public class DataRoomMinioServiceImpl implements IDataRoomOssService {
|
|
|
|
|
String extension = FilenameUtils.getExtension(originalFilename);
|
|
|
|
|
FileConfig fileConfig = bigScreenConfig.getFile();
|
|
|
|
|
if (!fileConfig.getAllowedFileExtensionName().contains("*") && !fileConfig.getAllowedFileExtensionName().contains(extension)) {
|
|
|
|
|
log.error("不支持 {} 文件类型",extension);
|
|
|
|
|
log.error("不支持 {} 文件类型", extension);
|
|
|
|
|
throw new GlobalException("不支持的文件类型");
|
|
|
|
|
}
|
|
|
|
|
String module = request.getParameter("module");
|
|
|
|
@ -77,31 +73,74 @@ public class DataRoomMinioServiceImpl implements IDataRoomOssService {
|
|
|
|
|
// 重命名
|
|
|
|
|
String newFileName = IdWorker.getIdStr() + "." + extension;
|
|
|
|
|
// 组装路径:获取当前日期并格式化为"yyyy/mm/dd"格式的字符串
|
|
|
|
|
String filePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd")) + "/" + newFileName;
|
|
|
|
|
InputStream inputStream = file.getInputStream();
|
|
|
|
|
PutObjectArgs args = PutObjectArgs.builder()
|
|
|
|
|
String basePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
|
|
|
|
|
String filePath = basePath + "/" + newFileName;
|
|
|
|
|
MinioConfig minioConfig = bigScreenConfig.getFile().getMinio();
|
|
|
|
|
try (InputStream inputStream = file.getInputStream()) {
|
|
|
|
|
PutObjectArgs args = PutObjectArgs.builder()
|
|
|
|
|
.bucket(minioConfig.getBucketName())
|
|
|
|
|
.object(filePath)
|
|
|
|
|
.stream(inputStream, file.getSize(), -1)
|
|
|
|
|
.contentType(file.getContentType())
|
|
|
|
|
.build();
|
|
|
|
|
minioclient.putObject(args);
|
|
|
|
|
|
|
|
|
|
String url = minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + filePath;
|
|
|
|
|
minioclient.putObject(args);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("上传文件到Minio失败");
|
|
|
|
|
log.error(ExceptionUtils.getStackTrace(e));
|
|
|
|
|
throw new GlobalException("上传文件失败");
|
|
|
|
|
}
|
|
|
|
|
// 现在url存储文件的相对路径,对于minio来说,就是bucketName/文件名
|
|
|
|
|
String url = "/" + minioConfig.getBucketName() + "/" + filePath;
|
|
|
|
|
fileEntity.setOriginalName(originalFilename);
|
|
|
|
|
fileEntity.setNewName(newFileName);
|
|
|
|
|
fileEntity.setPath(filePath);
|
|
|
|
|
fileEntity.setSize(file.getSize());
|
|
|
|
|
fileEntity.setExtension(extension);
|
|
|
|
|
fileEntity.setUrl(url);
|
|
|
|
|
fileEntity.setModule(module);
|
|
|
|
|
fileEntity.setBucket(minioConfig.getBucketName());
|
|
|
|
|
return fileEntity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public DataRoomFileEntity upload(InputStream inputStream, String fileName, long size, DataRoomFileEntity entity) {
|
|
|
|
|
fileName = PathUtils.normalizePath(fileName);
|
|
|
|
|
String extension = FilenameUtils.getExtension(fileName);
|
|
|
|
|
MinioConfig minioConfig = bigScreenConfig.getFile().getMinio();
|
|
|
|
|
long fileSize = size == 0 ? -1 : size;
|
|
|
|
|
// 使用minio的最小分片大小
|
|
|
|
|
long partSize = fileSize == -1 ? ObjectWriteArgs.MIN_MULTIPART_SIZE : -1;
|
|
|
|
|
try {
|
|
|
|
|
PutObjectArgs args = PutObjectArgs.builder()
|
|
|
|
|
.bucket(minioConfig.getBucketName())
|
|
|
|
|
.object(fileName)
|
|
|
|
|
.stream(inputStream, fileSize, partSize)
|
|
|
|
|
.contentType("image/png")
|
|
|
|
|
.build();
|
|
|
|
|
minioclient.putObject(args);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("上传文件到Minio失败");
|
|
|
|
|
log.error(ExceptionUtils.getStackTrace(e));
|
|
|
|
|
throw new GlobalException("上传文件失败");
|
|
|
|
|
} finally {
|
|
|
|
|
IOUtils.closeQuietly(inputStream);
|
|
|
|
|
}
|
|
|
|
|
// 现在url存储文件的相对路径,对于minio来说,就是bucketName/文件名
|
|
|
|
|
String url = "/" + minioConfig.getBucketName() + "/" + fileName;
|
|
|
|
|
entity.setOriginalName(fileName);
|
|
|
|
|
entity.setNewName(fileName);
|
|
|
|
|
entity.setPath(fileName);
|
|
|
|
|
entity.setSize(fileSize);
|
|
|
|
|
entity.setExtension(extension);
|
|
|
|
|
entity.setUrl(url);
|
|
|
|
|
entity.setBucket(minioConfig.getBucketName());
|
|
|
|
|
return entity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 下载文件
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
@SneakyThrows
|
|
|
|
|
@Override
|
|
|
|
|
public void download(String fileId, HttpServletResponse response, HttpServletRequest request) {
|
|
|
|
|
DataRoomFileEntity fileEntity = sysFileService.getById(fileId);
|
|
|
|
@ -114,9 +153,14 @@ public class DataRoomMinioServiceImpl implements IDataRoomOssService {
|
|
|
|
|
response.setContentType("multipart/form-data");
|
|
|
|
|
// 不设置前端无法从header获取文件名
|
|
|
|
|
response.setHeader("Access-Control-Expose-Headers", "filename");
|
|
|
|
|
response.setHeader("filename", URLEncoder.encode(fileEntity.getOriginalName(), "UTF-8"));
|
|
|
|
|
// 解决下载的文件不携带后缀
|
|
|
|
|
response.setHeader("Content-Disposition", "attachment;fileName="+URLEncoder.encode(fileEntity.getOriginalName(), "UTF-8"));
|
|
|
|
|
try {
|
|
|
|
|
response.setHeader("filename", URLEncoder.encode(fileEntity.getOriginalName(), "UTF-8"));
|
|
|
|
|
// 解决下载的文件不携带后缀
|
|
|
|
|
response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(fileEntity.getOriginalName(), "UTF-8"));
|
|
|
|
|
} catch (UnsupportedEncodingException e) {
|
|
|
|
|
log.error("文件名编码失败");
|
|
|
|
|
log.error(ExceptionUtils.getStackTrace(e));
|
|
|
|
|
}
|
|
|
|
|
try {
|
|
|
|
|
InputStream is = minioFileInterface.download(fileEntity.getPath());
|
|
|
|
|
IOUtils.copy(is, response.getOutputStream());
|
|
|
|
@ -124,7 +168,8 @@ public class DataRoomMinioServiceImpl implements IDataRoomOssService {
|
|
|
|
|
response.getOutputStream().close();
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
|
|
|
|
|
log.error(String.format("下载文件%s失败", fileEntity.getOriginalName()));
|
|
|
|
|
log.error("下载文件失败: {}", fileEntity.getPath());
|
|
|
|
|
log.error(ExceptionUtils.getStackTrace(e));
|
|
|
|
|
} finally {
|
|
|
|
|
sysFileService.updateDownloadCount(1, fileId);
|
|
|
|
|
}
|
|
|
|
@ -133,10 +178,39 @@ public class DataRoomMinioServiceImpl implements IDataRoomOssService {
|
|
|
|
|
/**
|
|
|
|
|
* 删除文件
|
|
|
|
|
*/
|
|
|
|
|
@SneakyThrows
|
|
|
|
|
@Override
|
|
|
|
|
public void delete(String fileId) {
|
|
|
|
|
String path = sysFileService.getById(fileId).getPath();
|
|
|
|
|
minioFileInterface.deleteObject(path.substring(path.indexOf(minioConfig.getBucketName())+minioConfig.getBucketName().length()+1));
|
|
|
|
|
DataRoomFileEntity fileEntity = sysFileService.getById(fileId);
|
|
|
|
|
if (fileEntity == null) {
|
|
|
|
|
log.error("删除的文件不存在");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
sysFileService.removeById(fileId);
|
|
|
|
|
String path = fileEntity.getPath();
|
|
|
|
|
try {
|
|
|
|
|
minioFileInterface.deleteObject(path);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("删除Minio文件失败: {}", path);
|
|
|
|
|
log.error(ExceptionUtils.getStackTrace(e));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public String copy(String sourcePath, String targetPath) {
|
|
|
|
|
MinioConfig minioConfig = bigScreenConfig.getFile().getMinio();
|
|
|
|
|
CopySource source = CopySource.builder().bucket(minioConfig.getBucketName()).object(sourcePath).build();
|
|
|
|
|
CopyObjectArgs args = CopyObjectArgs.builder()
|
|
|
|
|
.bucket(minioConfig.getBucketName())
|
|
|
|
|
.object(PathUtils.normalizePath(targetPath))
|
|
|
|
|
.source(source)
|
|
|
|
|
.build();
|
|
|
|
|
try {
|
|
|
|
|
minioclient.copyObject(args);
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("复制Minio文件失败: {}", sourcePath);
|
|
|
|
|
log.error(ExceptionUtils.getStackTrace(e));
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
return minioConfig.getBucketName() + "/" + targetPath;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|