# Minio工具类

```java
package cn.bunny.module.minio.utils;

import cn.bunny.common.service.exception.BunnyException;
import cn.bunny.module.minio.properties.MinioProperties;
import cn.bunny.pojo.constant.FileMessageConstant;
import cn.bunny.pojo.constant.MinioConstant;
import cn.bunny.pojo.file.MinioFIlePath;
import io.minio.*;
import io.minio.messages.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Minio操作工具类 简化操作步骤
 * By：Bunny0212
 */
@Component
@Slf4j
public class MinioUtil {
    @Autowired
    private MinioProperties properties;
    @Autowired
    private MinioClient minioClient;

    /**
     * 获取Minio文件路径
     */
    public static MinioFIlePath getMinioFilePath(String buckName, String minioPreType, MultipartFile file) {
        String uuid = UUID.randomUUID().toString();
        // 定义日期时间格式
        LocalDateTime currentDateTime = LocalDateTime.now();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM-dd");
        String extension = "";

        // 原始文件名
        String filename = file.getOriginalFilename();
        if (StringUtils.hasText(filename) && filename.contains(".")) {
            extension = "." + filename.substring(filename.lastIndexOf(".") + 1);
        }

        // UUID防止重名
        String uuidFilename = uuid + extension;

        // 拼接时间+UUID文件名
        String timeUuidFilename = currentDateTime.format(formatter) + "/" + uuidFilename;// 加上时间路径

        // 上传根文件夹+拼接时间+UUID文件名
        String filepath = MinioConstant.getType(minioPreType) + timeUuidFilename;

        // 桶名称+上传根文件夹+拼接时间+UUID文件名
        String buckNameFilepath = "/" + buckName + MinioConstant.getType(minioPreType) + timeUuidFilename;

        // 设置及Minio基础信息
        MinioFIlePath minioFIlePath = new MinioFIlePath();
        minioFIlePath.setFilename(filename);
        minioFIlePath.setUuidFilename(uuidFilename);
        minioFIlePath.setTimeUuidFilename(timeUuidFilename);
        minioFIlePath.setFilepath(filepath);
        minioFIlePath.setBucketNameFilepath(buckNameFilepath);

        return minioFIlePath;
    }

    /**
     * 上传文件
     *
     * @return 返回上传路径
     */
    public String uploadFile(MultipartFile file, String bucketName, String minioPreType) throws IOException {
        return getUploadFilePath(file, bucketName, minioPreType);
    }

    /**
     * 上传文件
     *
     * @return 返回上传路径
     */
    public String uploadFile(MultipartFile file, String minioPreType) throws IOException {
        // 如果buckName为空，设置为默认的桶
        String bucketName = properties.getBucketName();

        return getUploadFilePath(file, bucketName, minioPreType);
    }

    /**
     * * 上传文件
     *
     * @return 上传路径
     */
    private String getUploadFilePath(MultipartFile file, String bucketName, String minioPreType) throws IOException {
        if (file != null) {
            MinioFIlePath minioFile = getMinioFilePath(bucketName, minioPreType, file);
            String bucketNameFilepath = minioFile.getBucketNameFilepath();
            String filepath = minioFile.getFilepath();

            // 上传对象
            putObject(bucketName, filepath, file.getInputStream(), file.getSize());

            // 设置图片地址
            return bucketNameFilepath;
        }
        return null;
    }

    /**
     * * 上传文件
     *
     * @return 上传路径
     */
    public MinioFIlePath getUploadMinioObjectFilePath(MultipartFile file, String bucketName, String minioPreType) throws IOException {
        if (file != null) {
            MinioFIlePath minioFile = getMinioFilePath(bucketName, minioPreType, file);
            String filepath = minioFile.getFilepath();

            // 上传对象
            putObject(bucketName, filepath, file.getInputStream(), file.getSize());

            // 设置图片地址
            return minioFile;
        }
        return null;
    }

    /**
     * * 上传文件并返回处理信息
     */
    public MinioFIlePath getUploadMinioObjectFilePath(MultipartFile file, String minioPreType) throws IOException {
        // 如果buckName为空，设置为默认的桶
        String bucketName = properties.getBucketName();
        if (file != null) {
            MinioFIlePath minioFile = getMinioFilePath(bucketName, minioPreType, file);
            String filepath = minioFile.getFilepath();

            // 上传对象
            putObject(bucketName, filepath, file.getInputStream(), file.getSize());

            // 设置图片地址
            return minioFile;
        }
        return null;
    }

    /**
     * 获取文件并返回字节数组
     *
     * @param bucketName 桶名称
     * @param objectName 对象名称
     * @return 文件流对象
     */
    public byte[] getBucketObjectByte(String bucketName, String objectName) {
        try {
            GetObjectResponse getObjectResponse = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
            return getObjectResponse.readAllBytes();
        } catch (Exception exception) {
            exception.getStackTrace();
        }
        throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
    }

    /**
     * 获取默认bucket文件，并返回字节数组
     *
     * @param objectName 对象名称
     * @return 文件流对象
     */
    public byte[] getBucketObjectByte(String objectName) {
        // 如果buckName为空，设置为默认的桶
        String bucketName = properties.getBucketName();

        try {
            objectName = objectName.replace("/" + bucketName, "");
            GetObjectResponse getObjectResponse = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());

            return getObjectResponse.readAllBytes();
        } catch (Exception exception) {
            exception.getStackTrace();
        }
        throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
    }

    /**
     * 获取Minio全路径名，Object带有桶名称
     *
     * @param objectName 对象名称
     * @return 全路径
     */
    public String getObjectNameFullPath(String objectName) {
        String url = properties.getEndpointUrl();

        return url + objectName;
    }

    /**
     * 获取Minio全路径名-默认桶名称
     *
     * @param objectName 对象名称
     * @return 全路径
     */
    public String getDefaultBuckNameFullPath(String objectName) {
        String url = properties.getEndpointUrl();
        String bucketName = properties.getBucketName();

        return url + "/" + bucketName + objectName;
    }

    /**
     * 获取Minio全路径名，自定义桶名称
     *
     * @param objectName 对象名称
     * @return 全路径
     */
    public String getBuckNameFullPath(String bucketName, String objectName) {
        String url = properties.getEndpointUrl();

        return url + "/" + bucketName + objectName;
    }

    /**
     * 判断桶是否存在
     *
     * @param bucketName 桶名称
     * @return 布尔值，是否存在
     */
    public boolean bucketExists(String bucketName) {
        boolean found = false;
        try {
            found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            return found;
        } catch (Exception exception) {
            log.error("判断桶是否存在 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
        }
        throw new BunnyException(FileMessageConstant.BUCKET_EXISTS_EXCEPTION);
    }

    /**
     * 删除桶的加密配置
     *
     * @param bucketName 桶名称
     */
    public void deleteBucketEncryption(String bucketName) {
        try {
            minioClient.deleteBucketEncryption(DeleteBucketEncryptionArgs.builder().build());
            log.info("删除桶的加密配置 ------ 成功");
        } catch (Exception exception) {
            log.error("删除桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
        }
        throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
    }

    /**
     * 删除桶的生命周期配置
     *
     * @param bucketName 桶名称
     */
    public void deleteBucketLifecycle(String bucketName) {
        try {
            minioClient.deleteBucketLifecycle(DeleteBucketLifecycleArgs.builder().build());
            log.info("删除桶的生命周期配置 ------ 成功");
        } catch (Exception exception) {
            log.error("删除桶的生命周期配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 删除桶的通知配置
     *
     * @param bucketName 桶的名称
     */
    public void deleteBucketNotification(String bucketName) {
        try {
            minioClient.deleteBucketNotification(DeleteBucketNotificationArgs.builder().bucket(bucketName).build());
            log.info("删除桶的通知配置 ------ 成功");
        } catch (Exception exception) {
            log.error("删除桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 删除桶策略配置
     *
     * @param bucketName 桶的名称
     */
    public void deleteBucketPolicy(String bucketName) {
        try {
            minioClient.deleteBucketPolicy(DeleteBucketPolicyArgs.builder().bucket(bucketName).build());
            log.info("删除桶中的对象锁配置 ------ 成功");
        } catch (Exception exception) {
            log.error("删除桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 删除桶的桶复制配置
     *
     * @param bucketName 桶的名称
     */
    public void deleteBucketReplication(String bucketName) {
        try {
            minioClient.deleteBucketReplication(DeleteBucketReplicationArgs.builder().bucket(bucketName).build());
            log.info("删除桶的桶复制配置 ------ 成功");
        } catch (Exception exception) {
            log.error("删除桶的桶复制配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 删除桶的标签
     *
     * @param bucketName 桶的名称
     */
    public void deleteBucketTags(String bucketName) {
        try {
            minioClient.deleteBucketTags(DeleteBucketTagsArgs.builder().bucket(bucketName).build());
            log.info("删除桶的标签 ------ 成功");
        } catch (Exception exception) {
            log.error("删除桶的桶复制配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 删除桶中的对象锁配置
     *
     * @param bucketName 桶的名称
     */
    public void deleteObjectLockConfiguration(String bucketName) {
        try {
            minioClient.deleteObjectLockConfiguration(DeleteObjectLockConfigurationArgs.builder().bucket(bucketName).build());
            log.info("删除桶中的对象锁配置 ------ 成功");
        } catch (Exception exception) {
            log.error("删除桶中的对象锁配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 获取存储桶的加密配置
     *
     * @param bucketName 桶的名称
     * @return SseConfiguration 获取成功不为null
     */
    public SseConfiguration getBucketEncryption(String bucketName) {
        SseConfiguration conf = null;

        try {
            conf = minioClient.getBucketEncryption(GetBucketEncryptionArgs.builder().bucket(bucketName).build());
            log.info("获取存储桶的加密配置 ------ 成功");
        } catch (Exception exception) {
            log.error("获取存储桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
        }

        return conf;
    }

    /**
     * 获取存储桶的生命周期配置
     *
     * @param bucketName 桶的名称
     * @return LifecycleConfiguration 获取成功不为null
     */
    public LifecycleConfiguration getBucketLifecycle(String bucketName) {
        LifecycleConfiguration lifecycle = null;
        try {
            lifecycle = minioClient.getBucketLifecycle(GetBucketLifecycleArgs.builder().bucket(bucketName).build());
            log.info("获取存储桶的生命周期配置 ------ 成功");
        } catch (Exception exception) {
            log.error("获取存储桶的生命周期配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
        }

        return lifecycle;
    }

    /**
     * 获取存储桶的通知配置
     *
     * @param bucketName 桶的名称
     * @return NotificationConfiguration 获取成功不为null
     */
    public NotificationConfiguration getBucketNotification(String bucketName) {
        NotificationConfiguration configuration = null;

        try {
            configuration = minioClient.getBucketNotification(GetBucketNotificationArgs.builder().bucket(bucketName).build());
            log.info("获取存储桶的通知配置 ------ 成功");
        } catch (Exception exception) {
            log.error("获取存储桶的通知配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
        }

        return configuration;
    }

    /**
     * 获取桶的桶策略配置
     *
     * @param bucketName 桶的名称
     * @return String 获取成功不为null
     */
    public String getBucketPolicy(String bucketName) {
        String config = null;

        try {
            config = minioClient.getBucketPolicy(GetBucketPolicyArgs.builder().bucket(bucketName).build());
            log.info("获取桶的桶策略配置 ------ 成功");
        } catch (Exception exception) {
            log.error("获取桶的桶策略配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
        }

        return config;
    }

    /**
     * 获取桶复制参数
     *
     * @param bucketName 桶的名称
     * @return ReplicationConfiguration 获取成功不为null
     */
    public ReplicationConfiguration getBucketReplication(String bucketName) {
        ReplicationConfiguration configuration = null;

        try {
            configuration = minioClient.getBucketReplication(GetBucketReplicationArgs.builder().bucket(bucketName).build());
            log.info("获取桶复制参数 ------ 成功");
        } catch (Exception exception) {
            log.error("获取桶复制参数 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
        }

        return configuration;
    }

    /**
     * 获取存储桶的标签
     *
     * @param bucketName 桶的名称
     * @return Tags 获取成功不为null
     */
    public Tags getBucketTags(String bucketName) {
        Tags tags = null;

        try {
            tags = minioClient.getBucketTags(GetBucketTagsArgs.builder().bucket(bucketName).build());
            log.info("获取存储桶的标签 ------ 成功");
        } catch (Exception exception) {
            log.error("获取存储桶的标签 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
        }
        return tags;
    }

    /**
     * 获取存储桶的版本控制配置
     *
     * @param bucketName 桶的名称
     * @return Tags 获取成功不为null
     */
    public VersioningConfiguration getBucketVersioning(String bucketName) {
        VersioningConfiguration configuration = null;

        try {
            configuration = minioClient.getBucketVersioning(GetBucketVersioningArgs.builder().bucket(bucketName).build());
            log.info("获取存储桶的版本控制配置 ------ 成功");
        } catch (Exception exception) {
            log.error("获取存储桶的版本控制配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
        }

        return configuration;
    }

    /**
     * 获取存储桶中的对象锁配置
     *
     * @param bucketName 桶的名称
     * @return Tags 获取成功不为null
     */
    public ObjectLockConfiguration getObjectLockConfiguration(String bucketName) {
        ObjectLockConfiguration configuration = null;
        try {
            configuration = minioClient.getObjectLockConfiguration(GetObjectLockConfigurationArgs.builder().bucket(bucketName).build());
            log.info("获取存储桶中的对象锁配置 ------ 成功");
        } catch (Exception exception) {
            log.error("获取存储桶中的对象锁配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
        }

        return configuration;
    }

    /**
     * 列出所有桶的桶信息
     *
     * @return Tags 获取成功不为null
     */
    public List<Bucket> listBuckets() {
        List<Bucket> buckets = null;

        try {
            buckets = minioClient.listBuckets();
            log.info("列出所有桶的桶信息 ------ 成功");
        } catch (Exception exception) {
            log.error("列出所有桶的桶信息 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.QUERY_BUCKET_EXCEPTION);
        }

        return buckets;
    }

    /**
     * 创建桶
     *
     * @param bucketName 桶的名称
     */
    public void makeBucket(String bucketName) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        } catch (Exception exception) {
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.CREATE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 创建桶
     *
     * @param bucketName 桶的名称
     */
    public void makeBucket(String bucketName, String region) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).region(region).build());
        } catch (Exception exception) {
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.CREATE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 创建桶
     *
     * @param bucketName 桶的名称
     */
    public void makeBucket(String bucketName, String region, boolean objectLock) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).region(region).objectLock(objectLock).build());
            log.info("创建桶 ------ 成功");
        } catch (Exception exception) {
            log.error("创建桶 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.CREATE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 删除桶
     *
     * @param bucketName 桶的名称
     */
    public void removeBucket(String bucketName) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
            log.info("删除桶 ------ 成功");
        } catch (Exception exception) {
            log.error("删除桶 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 设置桶的加密配置
     *
     * @param bucketName    同名称
     * @param configuration 配置信息
     */
    public void setBucketEncryption(String bucketName, SseConfiguration configuration) {
        try {
            minioClient.setBucketEncryption(SetBucketEncryptionArgs.builder().bucket(bucketName).config(configuration).build());
            log.info("设置桶的加密配置 ------ 成功");
        } catch (Exception exception) {
            log.error("设置桶的加密配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 设置桶策略
     *
     * @param bucketName 同名称
     * @param policyJson 配置信息
     */
    public void setBucketPolicy(String bucketName, String policyJson) {
        try {
            minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(policyJson).build());
            log.info("查看桶策略 ------ 成功");
        } catch (Exception exception) {
            log.error("查看桶策略 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 设置桶复制参数
     *
     * @param bucketName 同名称
     * @param config     配置信息
     * @return 布尔值是否完成
     */
    public void setBucketReplication(String bucketName, ReplicationConfiguration config) {
        try {
            minioClient.setBucketReplication(SetBucketReplicationArgs.builder().bucket(bucketName).config(config).build());
            log.info("设置桶复制参数 ------ 成功");
        } catch (Exception exception) {
            log.error("设置桶复制参数 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 设置/修改桶标签
     *
     * @param bucketName 桶名称
     * @param map        标签集合
     */
    public void setBucketTags(String bucketName, Map<String, String> map) {
        try {
            minioClient.setBucketTags(SetBucketTagsArgs.builder().bucket(bucketName).tags(map).build());
            log.info("设置/修改桶标签 ------ 成功");
        } catch (Exception exception) {
            log.error("设置/修改桶标签 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 设置桶的版本配置
     *
     * @param bucketName    同名称
     * @param configuration 配置信息
     */
    public void setBucketVersioning(String bucketName, VersioningConfiguration configuration) {
        try {
            minioClient.setBucketVersioning(
                    SetBucketVersioningArgs.builder().bucket(bucketName).config(configuration).build());
            log.info("设置桶的版本配置 ------ 成功");
        } catch (Exception exception) {
            log.error("设置桶的版本配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 对象对象锁定配置
     *
     * @param bucketName    同名称
     * @param configuration 配置信息
     */
    public void setObjectLockConfiguration(String bucketName, ObjectLockConfiguration configuration) {
        try {
            minioClient.setObjectLockConfiguration(SetObjectLockConfigurationArgs.builder().bucket(bucketName).config(configuration).build());
            log.info("对象对象锁定配置 ------ 成功");
        } catch (Exception exception) {
            log.error("对象对象锁定配置 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 组合对象
     *
     * @param bucketName 同名称
     * @param objectName 对象名称
     * @param sources    对象列表
     */
    public void composeObject(String bucketName, String objectName, List<ComposeSource> sources) {
        try {
            minioClient.composeObject(ComposeObjectArgs.builder().bucket(bucketName).object(objectName).sources(sources).build());
            log.info("组合对象 ------ 成功");
        } catch (Exception exception) {
            log.error("组合对象 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.COMPOSE_OBJECT_EXCEPTION);
        }
    }

    /**
     * 组合对象
     *
     * @param bucketName   同名称
     * @param objectName   对象名称
     * @param sources      对象列表
     * @param userMetadata 用户元数据
     */
    public void composeObject(String bucketName, String objectName, List<ComposeSource> sources, Map<String, String> userMetadata) {
        try {
            minioClient.composeObject(ComposeObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .sources(sources)
                    .userMetadata(userMetadata).build());
            log.info("组合对象 ------ 成功");
        } catch (Exception exception) {
            log.error("组合对象 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.COMPOSE_OBJECT_EXCEPTION);
        }
    }

    /**
     * 组合对象
     *
     * @param bucketName     同名称
     * @param objectName     对象名称
     * @param sources        对象列表
     * @param userMetadata   用户元数据
     * @param sideEncryption 通过组合源对象列表
     */
    public void composeObject(String bucketName, String objectName, List<ComposeSource> sources, Map<String, String> userMetadata, ServerSideEncryption sideEncryption) {
        try {
            minioClient.composeObject(ComposeObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .sources(sources)
                    .userMetadata(userMetadata)
                    .sse(sideEncryption).build());
            log.info("组合对象 ------ 成功");
        } catch (Exception exception) {
            log.error("组合对象 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.COMPOSE_OBJECT_EXCEPTION);
        }
    }

    /**
     * 复制另一个桶中文件
     *
     * @param bucketName       桶中名字
     * @param objectName       复制名称
     * @param sourceBucketName 复制到桶中名称
     * @param sourceObjectName 复制完成后名称
     */
    public void copyObject(String bucketName, String objectName, String sourceBucketName, String sourceObjectName) {
        try {
            minioClient.copyObject(CopyObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .source(CopySource.builder().bucket(sourceBucketName).object(sourceObjectName).build())
                    .build());
            log.info("复制另一个桶中文件 ------ 成功");
        } catch (Exception exception) {
            log.error("复制另一个桶中文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.COPY_BUCKET_EXCEPTION);
        }
    }

    /**
     * 复制另一个桶中文件
     *
     * @param bucketName       桶中名字
     * @param objectName       复制名称
     * @param sourceBucketName 复制到桶中名称
     * @param sourceObjectName 复制完成后名称
     * @param sideEncryption   加密key
     */
    public void copyObject(String bucketName, String objectName, String sourceBucketName, String sourceObjectName, ServerSideEncryption sideEncryption) {
        try {
            minioClient.copyObject(CopyObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .source(CopySource.builder().bucket(sourceBucketName).object(sourceObjectName).build())
                    .sse(sideEncryption)
                    .build());
            log.info("复制另一个桶中文件 ------ 成功");
        } catch (Exception exception) {
            log.error("复制另一个桶中文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.COPY_BUCKET_EXCEPTION);
        }
    }

    /**
     * 复制另一个桶中文件
     *
     * @param bucketName       桶中名字
     * @param objectName       复制名称
     * @param sourceBucketName 复制到桶中名称
     * @param sourceObjectName 复制完成后名称
     * @param etag             标签
     * @param headers          头部信息
     */
    public void copyObject(String bucketName, String objectName, String sourceBucketName, String sourceObjectName, String etag, Map<String, String> headers) {
        try {
            minioClient.copyObject(CopyObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .source(CopySource.builder().bucket(sourceBucketName).object(sourceObjectName).matchETag(etag).build())
                    .headers(headers)
                    .build());
            log.info("复制另一个桶中文件 ------ 成功");
        } catch (Exception exception) {
            log.error("复制另一个桶中文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.COPY_BUCKET_EXCEPTION);
        }
    }

    /**
     * 删除对象的标记
     *
     * @param bucketName 桶中名字
     * @param objectName 复制名称
     */
    public void deleteObjectTags(String bucketName, String objectName) {
        try {
            minioClient.deleteObjectTags(DeleteObjectTagsArgs.builder().bucket(bucketName).object(objectName).build());
            log.info("删除对象的标记 ------ 成功");
        } catch (Exception exception) {
            log.error("删除对象的标记 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 禁用对象
     *
     * @param bucketName 桶中名字
     * @param objectName 复制名称
     */
    public void disableObjectLegalHold(String bucketName, String objectName) {
        try {
            minioClient.disableObjectLegalHold(DisableObjectLegalHoldArgs.builder().bucket(bucketName).object(objectName).build());
            log.info("禁用对象 ------ 成功");
        } catch (Exception exception) {
            log.error("禁用对象 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DISABLE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 启用文件对象
     *
     * @param bucketName 桶中名字
     * @param objectName 复制名称
     */
    public void enableObjectLegalHold(String bucketName, String objectName) {
        try {
            minioClient.enableObjectLegalHold(EnableObjectLegalHoldArgs.builder().bucket(bucketName).object(objectName).build());
            log.info("禁用对象 ------ 成功");
        } catch (Exception exception) {
            log.error("禁用对象 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.ENABLE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 获取文件
     *
     * @param bucketName 桶名称
     * @param objectName 对象名称
     */
    public InputStream getObject(String bucketName, String objectName) {
        try {
            GetObjectResponse object = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
            log.info("获取文件 ------ 成功");
            return object;
        } catch (Exception exception) {
            log.error("获取文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
        }
    }

    /**
     * 下载文件
     *
     * @param bucketName 桶名称
     * @param objectName 对象名称
     * @param filename   文件名
     */
    public void downloadObject(String bucketName, String objectName, String filename) {
        try {
            minioClient.downloadObject(DownloadObjectArgs.builder().bucket(bucketName).object(objectName).filename(filename).build());
            log.info("下载文件 ------ 成功");
        } catch (Exception exception) {
            log.error("下载文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DOWNLOAD_BUCKET_EXCEPTION);
        }
    }

    /**
     * 下载文件
     *
     * @param bucketName     桶名称
     * @param objectName     对象名称
     * @param filename       文件名
     * @param sideEncryption 秘钥
     */
    public void downloadObject(String bucketName, String objectName, String filename, ServerSideEncryptionCustomerKey sideEncryption) {
        try {
            minioClient.downloadObject(DownloadObjectArgs.builder().bucket(bucketName).object(objectName).filename(filename).ssec(sideEncryption).build());
            log.info("下载文件 ------ 成功");
        } catch (Exception exception) {
            log.error("下载文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DOWNLOAD_BUCKET_EXCEPTION);
        }
    }

    /**
     * 获取对象保留
     *
     * @param bucketName 桶名称
     * @param objectName 对象名称
     * @param versionId  版本ID
     * @return 对象保留
     */
    public Retention getObjectRetention(String bucketName, String objectName, String versionId) {
        try {
            Retention retention = minioClient.getObjectRetention(GetObjectRetentionArgs.builder().bucket(bucketName).object(objectName).versionId(versionId).build());
            log.info("获取对象保留 ------ 成功");
            return retention;
        } catch (Exception exception) {
            log.error("获取对象保留 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DOWNLOAD_BUCKET_EXCEPTION);
        }
    }

    /**
     * 获取对象标签
     *
     * @param bucketName 桶名称
     * @param objectName 对象名称
     * @return 对象保留
     */
    public Tags getObjectTags(String bucketName, String objectName) {
        try {
            Tags tags = minioClient.getObjectTags(GetObjectTagsArgs.builder().bucket(bucketName).object(objectName).build());
            log.info("获取对象标签 ------ 成功");
            return tags;
        } catch (Exception exception) {
            log.error("获取对象标签 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.GET_BUCKET_EXCEPTION);
        }
    }

    /**
     * 上传文件
     *
     * @param bucketName  桶名称
     * @param filename    文件名
     * @param inputStream 输入流
     * @param size        大小
     */
    public void putObject(String bucketName, String filename, InputStream inputStream, Long size) {
        try {
            minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(filename).stream(inputStream, size, -1).build());
        } catch (Exception exception) {
            log.error("上传文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.FILE_UPLOAD_EXCEPTION);
        }
    }

    /**
     * 上传文件
     *
     * @param bucketName  桶名称
     * @param filename    文件名
     * @param contentType 文件类型
     * @param inputStream 输入流
     * @param size        大小
     */
    public void putObject(String bucketName, String filename, String contentType, InputStream inputStream, Long size) {
        try {
            minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(filename).stream(inputStream, size, -1).contentType(contentType).build());
            log.info("上传文件 ------ 成功");
        } catch (Exception exception) {
            log.error("上传文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.FILE_UPLOAD_EXCEPTION);
        }
    }

    /**
     * 上传文件
     *
     * @param bucketName  桶名称
     * @param object      对象信息
     * @param filename    文件名
     * @param contentType 文件类型
     */
    public void putObject(String bucketName, String object, String filename, String contentType) {
        try {
            if (contentType != null) {
                minioClient.uploadObject(UploadObjectArgs.builder().bucket(bucketName).object(filename).contentType(contentType).build());
            } else {
                minioClient.uploadObject(UploadObjectArgs.builder().bucket(bucketName).object(filename).build());
            }
            log.info("上传文件 ------ 成功");
        } catch (Exception exception) {
            log.error("上传文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.FILE_UPLOAD_EXCEPTION);
        }
    }

    /**
     * 删除文件
     *
     * @param bucketName 桶名称
     * @param objectName 对象名称
     */
    public void removeObject(String bucketName, String objectName) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
            log.info("删除文件 ------ 成功");
        } catch (Exception exception) {
            log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 删除文件
     *
     * @param bucketName 桶名称
     * @param objectName 对象名称
     * @param versionId  版本号
     */
    public void removeObject(String bucketName, String objectName, String versionId) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).versionId(versionId).build());
            log.info("删除文件 ------ 成功");
        } catch (Exception exception) {
            log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 删除文件
     *
     * @param bucketName          桶名称
     * @param objectName          对象名称
     * @param bypassRetentionMode 保持模式
     */
    public void removeObject(String bucketName, String objectName, String versionId, boolean bypassRetentionMode) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).versionId(versionId).bypassGovernanceMode(bypassRetentionMode).build());
            log.info("删除文件 ------ 成功");
        } catch (Exception exception) {
            log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 上传多文件,通过创建中间TAR文件(可选压缩)来完成的
     *
     * @param bucketName 桶名称
     * @param objects    对象名称
     */
    public void uploadSnowballObjects(String bucketName, List<SnowballObject> objects) {
        try {
            minioClient.uploadSnowballObjects(UploadSnowballObjectsArgs.builder().bucket(bucketName).objects(objects).build());
            log.info("上传多文件 ------ 成功");
        } catch (Exception exception) {
            log.error("上传多文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.FILE_UPLOAD_EXCEPTION);
        }
    }

    /**
     * 设置对象标签
     *
     * @param bucketName           桶名称
     * @param objectName           对象名称
     * @param retention            配置信息
     * @param bypassGovernanceMode 保持模式
     */
    public void setObjectLockRetention(String bucketName, String objectName, Retention retention, boolean bypassGovernanceMode) {
        try {
            minioClient.setObjectRetention(SetObjectRetentionArgs.builder().bucket(bucketName).object(objectName).config(retention).bypassGovernanceMode(bypassGovernanceMode).build());
            log.info("删除文件 ------ 成功");
        } catch (Exception exception) {
            log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 设置对象标签
     *
     * @param bucketName 桶名称
     * @param objectName 对象名称
     * @param map        对象集合
     */
    public void setObjectTags(String bucketName, String objectName, Map<String, String> map) {
        try {
            minioClient.setObjectTags(SetObjectTagsArgs.builder().bucket(bucketName).object(objectName).tags(map).build());
            log.info("删除文件 ------ 成功");
        } catch (Exception exception) {
            log.error("删除文件 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.UPDATE_BUCKET_EXCEPTION);
        }
    }

    /**
     * 获取对象状态
     *
     * @param bucketName  桶名称
     * @param objectName  对象名称
     * @param versionId   版本ID
     * @param customerKey 秘钥
     * @return 对象信息
     */
    public StatObjectResponse statObject(String bucketName, String objectName, String versionId, ServerSideEncryptionCustomerKey customerKey) {
        try {
            StatObjectResponse statObjectResponse = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).versionId(versionId).ssec(customerKey).build());
            log.info("获取对象状态 ------ 成功");
            return statObjectResponse;
        } catch (Exception exception) {
            log.error("获取对象状态 ------ 失败消息:{}", exception.getLocalizedMessage());
            exception.getStackTrace();
            throw new BunnyException(FileMessageConstant.DELETE_BUCKET_EXCEPTION);
        }
    }
}
```

