From 6e4a12befbd74deb6831cfe1e0730cf9671418a7 Mon Sep 17 00:00:00 2001 From: zhouhaibin Date: Wed, 30 Oct 2024 16:20:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=96=E6=B6=88minio=E7=9A=84=E5=AF=BC?= =?UTF-8?q?=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- easy-file/pom.xml | 10 +- .../easy/admin/file/storage/FileStorage.java | 4 +- .../storage/type/local/FileStorageLocal.java | 10 +- .../storage/type/minio/FileStorageMinio.java | 495 ------------------ .../type/minio/config/MinioConfig.java | 32 -- 5 files changed, 10 insertions(+), 541 deletions(-) delete mode 100644 easy-file/src/main/java/com/easy/admin/file/storage/type/minio/FileStorageMinio.java delete mode 100644 easy-file/src/main/java/com/easy/admin/file/storage/type/minio/config/MinioConfig.java diff --git a/easy-file/pom.xml b/easy-file/pom.xml index 500de78..21149f8 100644 --- a/easy-file/pom.xml +++ b/easy-file/pom.xml @@ -50,11 +50,11 @@ test - - io.minio - minio - ${minio.version} - + + + + + diff --git a/easy-file/src/main/java/com/easy/admin/file/storage/FileStorage.java b/easy-file/src/main/java/com/easy/admin/file/storage/FileStorage.java index 625bdb7..baf4308 100644 --- a/easy-file/src/main/java/com/easy/admin/file/storage/FileStorage.java +++ b/easy-file/src/main/java/com/easy/admin/file/storage/FileStorage.java @@ -5,8 +5,6 @@ import com.easy.admin.file.model.StatObjectResponse; import com.easy.admin.file.storage.model.Bucket; import com.easy.admin.file.storage.model.PreSignatureParam; import com.easy.admin.file.storage.model.StorageObject; -import io.minio.Result; -import io.minio.messages.Item; import org.springframework.web.multipart.MultipartFile; import java.io.InputStream; @@ -165,7 +163,7 @@ public interface FileStorage { * @param recursive 是否递归查找,false:模拟文件夹结构查找 * @return 二进制流 */ - Iterable> listObjects(String bucketName, String prefix, boolean recursive); +// Iterable> listObjects(String bucketName, String prefix, boolean recursive); /** * 使用MultipartFile进行文件上传 diff --git a/easy-file/src/main/java/com/easy/admin/file/storage/type/local/FileStorageLocal.java b/easy-file/src/main/java/com/easy/admin/file/storage/type/local/FileStorageLocal.java index 2ebfa30..b5f942e 100644 --- a/easy-file/src/main/java/com/easy/admin/file/storage/type/local/FileStorageLocal.java +++ b/easy-file/src/main/java/com/easy/admin/file/storage/type/local/FileStorageLocal.java @@ -13,8 +13,6 @@ import com.easy.admin.file.storage.model.PreSignatureParam; import com.easy.admin.file.storage.model.StorageObject; import com.easy.admin.file.storage.properties.FileStorageProperties; import com.easy.admin.file.storage.properties.storage.FileStorageLocalProperties; -import io.minio.Result; -import io.minio.messages.Item; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -184,10 +182,10 @@ public class FileStorageLocal extends FileStorageAbstract { throw new EasyException("本地存储模式不支持[断点下载]"); } - @Override - public Iterable> listObjects(String bucketName, String prefix, boolean recursive) { - throw new EasyException("本地存储模式不支持[获取路径下文件列表]"); - } +// @Override +// public Iterable> listObjects(String bucketName, String prefix, boolean recursive) { +// throw new EasyException("本地存储模式不支持[获取路径下文件列表]"); +// } @Override public FileUploadResponse uploadFile(String bucketName, MultipartFile file, String objectName, String contentType) { diff --git a/easy-file/src/main/java/com/easy/admin/file/storage/type/minio/FileStorageMinio.java b/easy-file/src/main/java/com/easy/admin/file/storage/type/minio/FileStorageMinio.java deleted file mode 100644 index 0d84347..0000000 --- a/easy-file/src/main/java/com/easy/admin/file/storage/type/minio/FileStorageMinio.java +++ /dev/null @@ -1,495 +0,0 @@ -package com.easy.admin.file.storage.type.minio; - -import cn.hutool.core.codec.Base64Decoder; -import cn.hutool.core.io.FileUtil; -import cn.hutool.core.lang.UUID; -import cn.hutool.core.util.StrUtil; -import com.easy.admin.common.core.exception.EasyException; -import com.easy.admin.file.model.FileUploadResponse; -import com.easy.admin.file.model.StatObjectResponse; -import com.easy.admin.file.storage.FileStorage; -import com.easy.admin.file.storage.FileStorageAbstract; -import com.easy.admin.file.storage.common.constant.FileStoragePathConstant; -import com.easy.admin.file.storage.model.Bucket; -import com.easy.admin.file.storage.model.PreSignatureParam; -import com.easy.admin.file.storage.model.StorageObject; -import com.easy.admin.file.storage.properties.FileStorageProperties; -import com.easy.admin.file.storage.properties.storage.FileStorageLocalProperties; -import com.easy.admin.file.storage.properties.storage.FileStorageOSSProperties; -import com.easy.admin.file.storage.util.PreSignatureParamUtil; -import io.minio.*; -import io.minio.errors.*; -import io.minio.messages.Item; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.springframework.web.multipart.MultipartFile; - -import java.io.ByteArrayInputStream; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.time.ZonedDateTime; -import java.util.*; - -/** - * Minio 对象存储 - * - * @author TengChongChong - * @date 2023-10-25 - **/ -@Component -public class FileStorageMinio extends FileStorageAbstract implements FileStorage { - - private final Logger logger = LoggerFactory.getLogger(this.getClass()); - - @Autowired - private FileStorageProperties fileStorageProperties; - - /** - * local - 本地存储 - */ - @Autowired - private FileStorageLocalProperties localProperties; - - /** - * oss - 对象存储 - */ - @Autowired - private FileStorageOSSProperties ossProperties; - - @Autowired(required = false) - private MinioClient minioClient; - - @Override - public Map preSignature(PreSignatureParam preSignatureParam) { - // 桶 - if (StrUtil.isBlank(preSignatureParam.getBucket())) { - preSignatureParam.setBucket(fileStorageProperties.getDefaultBucket()); - } - - // 文件名 - if (StrUtil.isBlank(preSignatureParam.getFilename())) { - preSignatureParam.setFilename(UUID.fastUUID().toString()); - } - - // 凭证有效期 10 分钟 - ZonedDateTime expirationDate = ZonedDateTime.now().plusMinutes(10); - - // 创建凭证 - PostPolicy policy = new PostPolicy(preSignatureParam.getBucket(), expirationDate); - - // 设置文件名称 - policy.addEqualsCondition("key", preSignatureParam.getFilename()); - - // 设置允许上传的文件类型 - policy.addStartsWithCondition("Content-Type", preSignatureParam.getContentType()); - - // 设置允许上传的文件长度范围,默认最小长度1b,默认最大长度会根据系统参数设置中的`ossUpperLimit`参数设置,如未设置默认为1gb - policy.addContentLengthRangeCondition( - PreSignatureParamUtil.getLowerLimit(preSignatureParam.getLowerLimit()), - PreSignatureParamUtil.getUpperLimit(preSignatureParam.getUpperLimit()) - ); - - try { - return minioClient.getPresignedPostFormData(policy); - } catch (MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException e) { - logger.debug("获取签名失败,{}", e.getMessage()); - throw new EasyException("获取签名失败," + e.getMessage()); - } - } - - @Override - public boolean bucketExists(String bucketName) { - try { - return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); - } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | - InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | - XmlParserException e) { - logger.error("判断Bucket是否存在失败,{}", e.getMessage()); - throw new EasyException("判断Bucket是否存在失败," + e.getMessage()); - } - } - - @Override - public String getBucketPolicy(String bucketName) { - try { - return minioClient.getBucketPolicy(GetBucketPolicyArgs - .builder() - .bucket(bucketName) - .build()); - } catch (Exception e) { - logger.error("获得Bucket的策略失败,{}", e.getMessage()); - throw new EasyException("获得Bucket的策略失败," + e.getMessage()); - } - } - - @Override - public List getAllBuckets() { - try { - List bucketList = minioClient.listBuckets(); - List buckets = new ArrayList<>(); - bucketList.forEach(bucket -> { - buckets.add(new Bucket(bucket.name(), Date.from(bucket.creationDate().toInstant()))); - }); - return buckets; - } catch (Exception e) { - logger.error("获得所有Bucket列表失败,{}", e.getMessage()); - throw new EasyException("获得所有Bucket列表失败," + e.getMessage()); - } - } - - @Override - public Optional getBucket(String bucketName) { - return getAllBuckets().stream().filter(b -> b.getName().equals(bucketName)).findFirst(); - } - - @Override - public void removeBucket(String bucketName) { - try { - minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build()); - } catch (Exception e) { - logger.error("根据bucketName删除Bucket失败,{}", e.getMessage()); - throw new EasyException("根据bucketName删除Bucket失败," + e.getMessage()); - } - } - - @Override - public String getTemporaryPath() { - return FileStoragePathConstant.TEMPORARY + "/" + getDatePath() + "/"; - } - - @Override - public String getFormalPath() { - return FileStoragePathConstant.FORMAL + "/" + getDatePath() + "/"; - } - - @Override - public String moveToFormal(String bucketName, String objectName) { - return copyFile(bucketName, objectName, bucketName, objectName.replace(FileStoragePathConstant.TEMPORARY, FileStoragePathConstant.FORMAL)).getObjectName(); - } - - @Override - public boolean isObjectExist(String bucketName, String objectName) { - boolean exist = true; - try { - minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build()); - } catch (Exception e) { - logger.error("判断文件是否存在失败,{}", e.getMessage()); - throw new EasyException("判断文件是否存在失败," + e.getMessage()); - } - - return exist; - } - - @Override - public boolean isFolderExist(String bucketName, String objectName) { - boolean exist = false; - try { - Iterable> results = minioClient.listObjects( - ListObjectsArgs.builder().bucket(bucketName).prefix(objectName).recursive(false).build() - ); - for (Result result : results) { - Item item = result.get(); - if (item.isDir() && objectName.equals(item.objectName())) { - exist = true; - } - } - } catch (Exception e) { - logger.error("判断文件夹是否存在失败,", e); - throw new EasyException("判断文件夹是否存在失败," + e.getMessage()); - } - return exist; - } - - @Override - public List getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) { - try { - if (!prefix.endsWith("/")) { - prefix += "/"; - } - List list = new ArrayList<>(); - Iterable> objectsIterator = minioClient.listObjects( - ListObjectsArgs.builder().bucket(bucketName).prefix(prefix).recursive(recursive).build() - ); - if (objectsIterator != null) { - for (Result object : objectsIterator) { - Item item = object.get(); - list.add(new StorageObject(item.objectName(), item.isDir())); - } - } - return list; - } catch (Exception e) { - logger.error("根据文件前缀查询文件失败,", e); - throw new EasyException("根据文件前缀查询文件失败," + e.getMessage()); - } - } - - @Override - public String downloadToLocalTemporaryPath(String bucketName, String objectName) { - String localTemporaryPath = getLocalTemporaryPath(); - String fileName = objectName.substring(objectName.lastIndexOf(File.separator) + 1); - String fullFilePath = localTemporaryPath + fileName; - // 写入文件 - FileUtil.writeFromStream(getObject(bucketName, objectName), fullFilePath); - return fullFilePath; - } - - /** - * 获取本地磁盘临时文件目录 - * - * @return 路径 - */ - private String getLocalTemporaryPath() { - File file = new File( - localProperties.getPath() + - fileStorageProperties.getDefaultBucket() + File.separator + - FileStoragePathConstant.TEMPORARY + File.separator + - getDatePath() - ); - checkDirs(file); - return file.getPath() + File.separator; - } - - /** - * 检查文件夹是否存在,如不存在则新建 - * - * @param file 文件 - */ - private void checkDirs(File file) { - if (!file.exists() && !file.mkdirs()) { - throw new EasyException("文件创建失败[" + file.getPath() + "]"); - } - } - - @Override - public InputStream getObject(String bucketName, String objectName) { - try { - return minioClient.getObject( - GetObjectArgs.builder() - .bucket(bucketName) - .object(objectName) - .build()); - } catch (Exception e) { - logger.error("获取文件流失败,", e); - throw new EasyException("获取文件流失败," + e.getMessage()); - } - } - - @Override - public InputStream getObject(String bucketName, String objectName, long offset, long length) { - try { - return minioClient.getObject( - GetObjectArgs.builder() - .bucket(bucketName) - .object(objectName) - .build()); - } catch (Exception e) { - logger.error("断点下载失败,", e); - throw new EasyException("断点下载失败," + e.getMessage()); - } - } - - @Override - public Iterable> listObjects(String bucketName, String prefix, boolean recursive) { - try { - return minioClient.listObjects( - ListObjectsArgs.builder() - .bucket(bucketName) - .prefix(prefix) - .recursive(recursive) - .build()); - } catch (Exception e) { - logger.error("获取路径下文件列表失败,", e); - throw new EasyException("获取路径下文件列表失败," + e.getMessage()); - } - } - - @Override - public FileUploadResponse uploadFile(String bucketName, MultipartFile file, String objectName, String contentType) { - try { - InputStream inputStream = file.getInputStream(); - return convert(minioClient.putObject( - PutObjectArgs.builder() - .bucket(bucketName) - .object(objectName) - .contentType(contentType) - .stream(inputStream, inputStream.available(), -1) - .build())); - } catch (Exception e) { - logger.error("使用MultipartFile进行文件上传失败,", e); - throw new EasyException("使用MultipartFile进行文件上传失败," + e.getMessage()); - } - } - - @Override - public FileUploadResponse uploadImage(String bucketName, String imageBase64, String objectName) { - if (StrUtil.isEmpty(imageBase64)) { - throw new EasyException("图片上传失败,图片数据为空"); - } - try { - InputStream in = base64ToInputStream(imageBase64); - return uploadFile(bucketName, objectName, in); - } catch (Exception e) { - logger.error("图片上传失败,", e); - throw new EasyException("图片上传失败," + e.getMessage()); - } - } - - private static InputStream base64ToInputStream(String base64) { - byte[] bytes = Base64Decoder.decode(base64.trim()); - return new ByteArrayInputStream(bytes); - } - - @Override - public FileUploadResponse uploadFile(String bucketName, String objectName, String filePath) { - try { - return convert(minioClient.uploadObject( - UploadObjectArgs.builder() - .bucket(bucketName) - .object(objectName) - .filename(filePath) - .build())); - } catch (Exception e) { - logger.error("上传本地文件失败,", e); - throw new EasyException("上传本地文件失败," + e.getMessage()); - } - } - - @Override - public FileUploadResponse uploadFile(String bucketName, String objectName, InputStream inputStream) { - try { - return convert(minioClient.putObject( - PutObjectArgs.builder() - .bucket(bucketName) - .object(objectName) - .stream(inputStream, inputStream.available(), -1) - .build())); - } catch (Exception e) { - logger.error("通过流上传文件失败,", e); - throw new EasyException("通过流上传文件失败," + e.getMessage()); - } - } - - @Override - public FileUploadResponse createDir(String bucketName, String objectName) { - try { - return convert(minioClient.putObject( - PutObjectArgs.builder() - .bucket(bucketName) - .object(objectName) - .stream(new ByteArrayInputStream(new byte[]{}), 0, -1) - .build())); - } catch (Exception e) { - logger.error("创建文件夹或目录失败,", e); - throw new EasyException("创建文件夹或目录失败," + e.getMessage()); - } - } - - @Override - public StatObjectResponse getStatObject(String bucketName, String objectName) { - try { - io.minio.StatObjectResponse statObject = minioClient.statObject( - StatObjectArgs.builder() - .bucket(bucketName) - .object(objectName) - .build()); - - return new StatObjectResponse(statObject.bucket(), statObject.object(), statObject.size()); - } catch (Exception e) { - logger.error("获取文件信息失败,", e); - throw new EasyException("获取文件信息失败," + e.getMessage()); - } - } - - @Override - public FileUploadResponse copyFile(String srcBucketName, String srcObjectName, String destBucketName, String destObjectName) { - try { - return convert(minioClient.copyObject( - CopyObjectArgs.builder() - .source(CopySource.builder().bucket(srcBucketName).object(srcObjectName).build()) - .bucket(destBucketName) - .object(destObjectName) - .build())); - } catch (Exception e) { - logger.error("拷贝文件失败,", e); - throw new EasyException("拷贝文件失败," + e.getMessage()); - } - } - - @Override - public void removeFile(String bucketName, String objectName) { - try { - if (objectName.endsWith(".") || objectName.endsWith("/")) { - Iterable> list = minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).prefix(objectName).recursive(true).build()); - for (Result itemResult : list) { - Item item = itemResult.get(); - removeFile(bucketName, item.objectName()); - } - } else { - minioClient.removeObject( - RemoveObjectArgs.builder() - .bucket(bucketName) - .object(objectName) - .build()); - } - } catch (Exception e) { - logger.error("删除文件失败,", e); - throw new EasyException("删除文件失败," + e.getMessage()); - } - } - - @Override - public void removeFiles(String bucketName, List objectNames) { - try { - objectNames.forEach(objectName -> { - removeFile(bucketName, objectName); - }); - } catch (Exception e) { - logger.error("批量删除文件失败,", e); - throw new EasyException("批量删除文件失败," + e.getMessage()); - } - } - - @Override - public String getFileUrl(String bucketName, String objectName, Integer expires) { - try { - GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder().expiry(expires).bucket(bucketName).object(objectName).build(); - return minioClient.getPresignedObjectUrl(args); - } catch (Exception e) { - logger.error("获取文件外链失败,", e); - throw new EasyException("获取文件外链失败," + e.getMessage()); - } - } - - @Override - public String getFileUrl(String bucketName, String objectName) { - //try { - // GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder() - // .bucket(bucketName) - // .object(objectName) - // .method(Method.GET).build(); - // return minioClient.getPresignedObjectUrl(args); - //} catch (Exception e) { - // logger.error("获得文件外链失败,", e); - // throw new EasyException("获得文件外链失败," + e.getMessage()); - //} - return ossProperties.getEndpoint() + "/" + bucketName + "/" + objectName; - } - - /** - * 转为FileUploadResponse - * - * @param response ObjectWriteResponse - * @return FileUploadResponse - */ - private FileUploadResponse convert(ObjectWriteResponse response) { - FileUploadResponse fileUploadResponse = new FileUploadResponse(response.bucket(), response.object()); - // 获取预览/下载地址 - fileUploadResponse.setUrl(getFileUrl(fileUploadResponse.getBucketName(), fileUploadResponse.getObjectName())); - return fileUploadResponse; - } -} diff --git a/easy-file/src/main/java/com/easy/admin/file/storage/type/minio/config/MinioConfig.java b/easy-file/src/main/java/com/easy/admin/file/storage/type/minio/config/MinioConfig.java deleted file mode 100644 index 908c1b2..0000000 --- a/easy-file/src/main/java/com/easy/admin/file/storage/type/minio/config/MinioConfig.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.easy.admin.file.storage.type.minio.config; - -import cn.hutool.core.util.StrUtil; -import com.easy.admin.file.storage.common.type.FileStorageEnum; -import com.easy.admin.file.storage.properties.FileStorageProperties; -import com.easy.admin.file.storage.properties.storage.FileStorageOSSProperties; -import io.minio.MinioClient; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; - -/** - * MinIO 对象存储 - * - * @author TengChongChong - * @date 2023-10-25 - **/ -@Configuration -public class MinioConfig { - - @Bean - public MinioClient minioClient(FileStorageProperties fileStorageProperties, FileStorageOSSProperties ossProperties) { - if (!fileStorageProperties.enableOss() || !FileStorageEnum.MINIO.getCode().equals(ossProperties.getType())) { - return null; - } - MinioClient.Builder builder = MinioClient.builder(); - builder.endpoint(ossProperties.getEndpoint()); - if (StrUtil.isNotBlank(ossProperties.getAccessKey()) && StrUtil.isNotBlank(ossProperties.getSecretKey())) { - builder.credentials(ossProperties.getAccessKey(), ossProperties.getSecretKey()); - } - return builder.build(); - } -}