refactor: MinIO 上传图片返回名称不带文件夹和全局异常支持自定义异常信息。
This commit is contained in:
@@ -3,6 +3,13 @@ package com.youlai.boot.shared.file.model;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
|
||||
|
||||
/**
|
||||
* 文件信息对象
|
||||
*
|
||||
* @author Ray.Hao
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@Schema(description = "文件对象")
|
||||
@Data
|
||||
public class FileInfo {
|
||||
|
||||
@@ -5,30 +5,30 @@ import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.lang.Assert;
|
||||
import cn.hutool.core.util.IdUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.youlai.boot.common.exception.BusinessException;
|
||||
import com.youlai.boot.common.result.ResultCode;
|
||||
import com.youlai.boot.shared.file.service.FileService;
|
||||
import com.youlai.boot.shared.file.model.FileInfo;
|
||||
import io.minio.*;
|
||||
import io.minio.errors.*;
|
||||
import io.minio.http.Method;
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import lombok.Data;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* MinIO 文件上传服务类
|
||||
*
|
||||
* @author haoxr
|
||||
* @author Ray.Hao
|
||||
* @since 2023/6/2
|
||||
*/
|
||||
@Component
|
||||
@@ -36,6 +36,7 @@ import java.time.LocalDateTime;
|
||||
@ConfigurationProperties(prefix = "oss.minio")
|
||||
@RequiredArgsConstructor
|
||||
@Data
|
||||
@Slf4j
|
||||
public class MinioFileService implements FileService {
|
||||
|
||||
/**
|
||||
@@ -77,7 +78,7 @@ public class MinioFileService implements FileService {
|
||||
* 上传文件
|
||||
*
|
||||
* @param file 表单文件对象
|
||||
* @return
|
||||
* @return 文件信息
|
||||
*/
|
||||
@Override
|
||||
public FileInfo uploadFile(MultipartFile file) {
|
||||
@@ -85,16 +86,19 @@ public class MinioFileService implements FileService {
|
||||
// 创建存储桶(存储桶不存在),如果有搭建好的minio服务,建议放在init方法中
|
||||
createBucketIfAbsent(bucketName);
|
||||
|
||||
// 生成文件名(日期文件夹)
|
||||
// 文件后缀
|
||||
String suffix = FileUtil.getSuffix(file.getOriginalFilename());
|
||||
String uuid = IdUtil.simpleUUID();
|
||||
String fileName = DateUtil.format(LocalDateTime.now(), "yyyyMMdd") + "/" + uuid + "." + suffix;
|
||||
// 文件夹名称
|
||||
String dateFolder = DateUtil.format(LocalDateTime.now(), "yyyyMMdd");
|
||||
// 文件名称
|
||||
String fileName = IdUtil.simpleUUID() + "." + suffix;
|
||||
|
||||
// try-with-resource 语法糖自动释放流
|
||||
try (InputStream inputStream = file.getInputStream()) {
|
||||
// 文件上传
|
||||
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
|
||||
.bucket(bucketName)
|
||||
.object(fileName)
|
||||
.object(dateFolder + "/"+ fileName)
|
||||
.contentType(file.getContentType())
|
||||
.stream(inputStream, inputStream.available(), -1)
|
||||
.build();
|
||||
@@ -104,15 +108,18 @@ public class MinioFileService implements FileService {
|
||||
String fileUrl;
|
||||
// 未配置自定义域名
|
||||
if (StrUtil.isBlank(customDomain)) {
|
||||
// 获取文件URL
|
||||
GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder()
|
||||
.bucket(bucketName).object(fileName)
|
||||
.bucket(bucketName)
|
||||
.object(dateFolder + "/"+ fileName)
|
||||
.method(Method.GET)
|
||||
.build();
|
||||
|
||||
fileUrl = minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);
|
||||
fileUrl = fileUrl.substring(0, fileUrl.indexOf("?"));
|
||||
} else { // 配置自定义文件路径域名
|
||||
fileUrl = customDomain + '/' + bucketName + "/" + fileName;
|
||||
} else {
|
||||
// 配置自定义文件路径域名
|
||||
fileUrl = customDomain + "/"+ bucketName + "/"+ dateFolder + "/"+ fileName;
|
||||
}
|
||||
|
||||
FileInfo fileInfo = new FileInfo();
|
||||
@@ -120,7 +127,8 @@ public class MinioFileService implements FileService {
|
||||
fileInfo.setUrl(fileUrl);
|
||||
return fileInfo;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("文件上传失败");
|
||||
log.error("上传文件失败", e);
|
||||
throw new BusinessException(ResultCode.UPLOAD_FILE_EXCEPTION, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,9 +136,8 @@ public class MinioFileService implements FileService {
|
||||
/**
|
||||
* 删除文件
|
||||
*
|
||||
* @param filePath 文件路径 http://localhost:9000/default/20221120/test.jpg
|
||||
*
|
||||
* @return
|
||||
* @param filePath 文件完整路径
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
@Override
|
||||
public boolean deleteFile(String filePath) {
|
||||
@@ -152,7 +159,8 @@ public class MinioFileService implements FileService {
|
||||
minioClient.removeObject(removeObjectArgs);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("文件删除失败", e);
|
||||
log.error("删除文件失败", e);
|
||||
throw new BusinessException(ResultCode.DELETE_FILE_EXCEPTION, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -161,17 +169,11 @@ public class MinioFileService implements FileService {
|
||||
* PUBLIC桶策略
|
||||
* 如果不配置,则新建的存储桶默认是PRIVATE,则存储桶文件会拒绝访问 Access Denied
|
||||
*
|
||||
* @param bucketName
|
||||
* @return
|
||||
* @param bucketName 存储桶名称
|
||||
* @return 存储桶策略
|
||||
*/
|
||||
private static String publicBucketPolicy(String bucketName) {
|
||||
/**
|
||||
* AWS的S3存储桶策略
|
||||
* Principal: 生效用户对象
|
||||
* Resource: 指定存储桶
|
||||
* Action: 操作行为
|
||||
*/
|
||||
|
||||
// AWS的S3存储桶策略 JSON 格式 https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/example-bucket-policies.html
|
||||
return "{\"Version\":\"2012-10-17\","
|
||||
+ "\"Statement\":[{\"Effect\":\"Allow\","
|
||||
+ "\"Principal\":{\"AWS\":[\"*\"]},"
|
||||
@@ -185,7 +187,7 @@ public class MinioFileService implements FileService {
|
||||
/**
|
||||
* 创建存储桶(存储桶不存在)
|
||||
*
|
||||
* @param bucketName
|
||||
* @param bucketName 存储桶名称
|
||||
*/
|
||||
@SneakyThrows
|
||||
private void createBucketIfAbsent(String bucketName) {
|
||||
|
||||
Reference in New Issue
Block a user