minio单机安装及Springboot集成minio记录

minio官网地址:https://min.io/
minio官方下载地址:https://min.io/download#/linux
minio官方文档地址:https://min.io/docs/minio

linux minio单机安装

参考官方教程:

wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio
MINIO_ROOT_USER=minioadmin MINIO_ROOT_PASSWORD=minioadmin ./minio server /mnt/minio/data --console-address ":9001"

执行上方命令后,用浏览器访问本地9001端口即可看到控制台界面,用默认用户名密码登录即可,文件存储目录是上面指定的/mnt/minio/data目录
登录之后,可以在界面上创建自己的Bucket,生成accesskey,新建用户等
比如:可以新建test用户密码为test12345678A,配置好readwrite和diagnostics策略,新建testbucket桶,Access Policy设置为public。
minio默认的访问端口是9000,在界面上上传一张图片:2022-01-22_18-40.png
那么用本机ip端口9000就可以访问这个图片:
比如:http://127.0.0.1:9000/testbucket/2022-01-22_18-40.png

windows minio单机安装

参考官方教程:

PS> Invoke-WebRequest -Uri "https://dl.min.io/server/minio/release/windows-amd64/minio.exe" -OutFile "C:\minio.exe"
PS> setx MINIO_ROOT_USER admin
PS> setx MINIO_ROOT_PASSWORD password
PS> C:\minio.exe server F:\Data --console-address ":9001"

springboot集成minio

maven 引入(截止发文最新版本是8.5.6):

        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.5.6</version>
        </dependency>
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.12.0</version>
        </dependency>

配置application.properties

minio.endpoint=http://192.168.0.118:9000
minio.accessKey=test
minio.secretKey=test12345678A
minio.bucket=testbucket
minio.parentPath=project1

新建MinioProperties

package com.zhaohy.app.minio;

import org.hibernate.validator.constraints.URL;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

import jakarta.validation.constraints.NotEmpty;

@Component
@ConfigurationProperties(prefix = "minio")
public class MinioProperties {
    /**
     * 服务地址
     */
    @NotEmpty(message = "minio服务地址不可为空")
    @URL(message = "minio服务地址格式错误")
    private String endpoint;

    /**
     * 认证账户
     */
    @NotEmpty(message = "minio认证账户不可为空")
    private String accessKey;

    /**
     * 认证密码
     */
    @NotEmpty(message = "minio认证密码不可为空")
    private String secretKey;

    /**
     * 桶名称, 优先级最低
     */
    private String bucket;
    
    /**
     * bucket下面的第一个文件夹,用来区分不同子项目
     */
    private String parentPath;

    /**
     * 桶不在的时候是否新建桶
     */
    private boolean createBucket = true;

    /**
     * 启动的时候检查桶是否存在
     */
    private boolean checkBucket = true;

    /**
     * 设置HTTP连接、写入和读取超时。值为0意味着没有超时
     * HTTP连接超时,以毫秒为单位。
     */
    private long connectTimeout;

    /**
     * 设置HTTP连接、写入和读取超时。值为0意味着没有超时
     * HTTP写超时,以毫秒为单位。
     */
    private long writeTimeout;

    /**
     * 设置HTTP连接、写入和读取超时。值为0意味着没有超时
     * HTTP读取超时,以毫秒为单位。
     */
    private long readTimeout;

    public String getEndpoint() {
        return endpoint;
    }

    public void setEndpoint(String endpoint) {
        this.endpoint = endpoint;
    }

    public String getAccessKey() {
        return accessKey;
    }

    public void setAccessKey(String accessKey) {
        this.accessKey = accessKey;
    }

    public String getSecretKey() {
        return secretKey;
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    public String getBucket() {
        return bucket;
    }

    public void setBucket(String bucket) {
        this.bucket = bucket;
    }

    public boolean isCreateBucket() {
        return createBucket;
    }

    public void setCreateBucket(boolean createBucket) {
        this.createBucket = createBucket;
    }

    public boolean isCheckBucket() {
        return checkBucket;
    }

    public void setCheckBucket(boolean checkBucket) {
        this.checkBucket = checkBucket;
    }

    public long getConnectTimeout() {
        return connectTimeout;
    }

    public void setConnectTimeout(long connectTimeout) {
        this.connectTimeout = connectTimeout;
    }

    public long getWriteTimeout() {
        return writeTimeout;
    }

    public void setWriteTimeout(long writeTimeout) {
        this.writeTimeout = writeTimeout;
    }

    public long getReadTimeout() {
        return readTimeout;
    }

    public void setReadTimeout(long readTimeout) {
        this.readTimeout = readTimeout;
    }

    public String getParentPath() {
        return parentPath;
    }

    public void setParentPath(String parentPath) {
        this.parentPath = parentPath;
    }
}

新建MinioConfiguration

package com.zhaohy.app.minio;

import javax.annotation.Resource;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.zhaohy.app.utils.LogUtils;

import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;

@Configuration
public class MinioConfiguration {
    @Resource
    private MinioProperties minioAutoProperties;
    @Bean
    public MinioClient minioClient() {
        LogUtils.info("开始初始化MinioClient, url为{}, accessKey为:{}", minioAutoProperties.getEndpoint(), minioAutoProperties.getAccessKey());
        MinioClient minioClient = MinioClient
            .builder()
            .endpoint(minioAutoProperties.getEndpoint())
            .credentials(minioAutoProperties.getAccessKey(), minioAutoProperties.getSecretKey())
            .build();

        minioClient.setTimeout(
            minioAutoProperties.getConnectTimeout(),
            minioAutoProperties.getWriteTimeout(),
            minioAutoProperties.getReadTimeout()
        );
        // Start detection
        if (minioAutoProperties.isCheckBucket()) {
            LogUtils.info("checkBucket为{}, 开始检测桶是否存在", minioAutoProperties.isCheckBucket());
            String bucketName = minioAutoProperties.getBucket();
            if (!checkBucket(bucketName, minioClient)) {
                LogUtils.info("文件桶[{}]不存在, 开始检查是否可以新建桶", bucketName);
                if (minioAutoProperties.isCreateBucket()) {
                    LogUtils.info("createBucket为{},开始新建文件桶", minioAutoProperties.isCreateBucket());
                    createBucket(bucketName, minioClient);
                }
            }
            LogUtils.info("文件桶[{}]已存在, minio客户端连接成功!", bucketName);
        } else {
            throw new RuntimeException("桶不存在, 请检查桶名称是否正确或者将checkBucket属性改为false");
        }
        return minioClient;
    }

    private boolean checkBucket(String bucketName, MinioClient minioClient) {
        boolean isExists = false;
        try {
            isExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            throw new RuntimeException("failed to check if the bucket exists", e);
        }
        return isExists;
    }

    private void createBucket(String bucketName, MinioClient minioClient) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            LogUtils.info("文件桶[{}]新建成功, minio客户端已连接", bucketName);
        } catch (Exception e) {
            throw new RuntimeException("failed to create default bucket", e);
        }
    }
}

新建MinioPathUtils

package com.zhaohy.app.minio;

import java.util.UUID;

import com.zhaohy.app.utils.DateUtil;

public class MinioPathUtils {
    public static final String minioPath = "project1";
    public static final String extranetAddr = "http://192.168.0.118:9000";
    public static final String publicBucket = "testbucket";
    
    public static String getMinioTmpDir() {
        return minioPath + "/tmp/" + DateUtil.getSystemDate("yyyyMM") + "/" + UUID.randomUUID().toString().replace("-", "") + "/";
    }
    
    public static String getMinioDefaultDir() {
        return minioPath + "/" + DateUtil.getSystemDate("yyyyMM") + "/" + UUID.randomUUID().toString().replace("-", "") + "/";
    }
    
    public static String getMinioCustomDir(String path) {
        return minioPath + path + DateUtil.getSystemDate("yyyyMM") + "/" + UUID.randomUUID().toString().replace("-", "") + "/";
    }

    public static String getBaseUrl() {
        return extranetAddr + "/" + publicBucket + "/";
    }
}

新建MinioTemplate

package com.zhaohy.app.minio;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.function.IntFunction;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;

import io.minio.BucketExistsArgs;
import io.minio.CopyObjectArgs;
import io.minio.CopySource;
import io.minio.GetObjectArgs;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.ListObjectsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.ObjectWriteResponse;
import io.minio.PutObjectArgs;
import io.minio.RemoveBucketArgs;
import io.minio.RemoveObjectArgs;
import io.minio.Result;
import io.minio.StatObjectArgs;
import io.minio.StatObjectResponse;
import io.minio.errors.ErrorResponseException;
import io.minio.errors.InsufficientDataException;
import io.minio.errors.InternalException;
import io.minio.errors.InvalidResponseException;
import io.minio.errors.ServerException;
import io.minio.errors.XmlParserException;
import io.minio.messages.Bucket;
import io.minio.messages.Item;

@Component
public class MinioTemplate {
    @Resource
    private MinioClient minioClient;

    @Resource
    private MinioProperties minioProperties;
    
      /**
       * 判断文件是否存在
       *
       * @param bucketName 存储桶
       * @param objectName 对象
       * @return true:存在
       */
      public boolean doesObjectExist(String bucketName, String objectName) {
        boolean exist = true;
        try {
          minioClient
              .statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
        } catch (Exception e) {
          exist = false;
        }
        return exist;
      }
      
      /**
       * 判断文件夹是否存在
       *
       * @param bucketName 存储桶
       * @param objectName 文件夹名称(去掉/)
       * @return true:存在
       */
      public boolean doesFolderExist(String objectName) {
        boolean exist = false;
        try {
          Iterable<Result<Item>> results = minioClient.listObjects(
              ListObjectsArgs.builder().bucket(minioProperties.getBucket()).prefix(objectName).recursive(false).build());
          for (Result<Item> result : results) {
            Item item = result.get();
            if (item.isDir() && objectName.equals(item.objectName())) {
              exist = true;
            }
          }
        } catch (Exception e) {
          exist = false;
        }
        return exist;
      }
      
    /**
     * 判断桶是否存在
     *
     * @param bucketName bucket名称
     * @return true存在,false不存在
     */
    public Boolean bucketExists(String bucketName) {
        try {
            return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            throw new RuntimeException("检查桶是否存在失败!", e);
        }
    }

    /**
     * 创建bucket
     *
     * @param bucketName bucket名称
     */
    public void createBucket(String bucketName) {
        if (!this.bucketExists(bucketName)) {
            try {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            } catch (Exception e) {
                throw new RuntimeException("创建桶失败!", e);
            }
        }
    }



    /**
     * 上传bytes文件
     *
     * @param objectName  文件名
     * @param bytes       字节
     * @param contentType 文件类型, 例如 image/jpeg: jpg图片格式, 详细可看: https://www.runoob.com/http/http-content-type.html
     * @return 文件url
     */
    public String putObject(String objectName, byte[] bytes, String contentType) {
        // 开始上传
        this.putBytes(minioProperties.getBucket(), objectName, bytes, contentType);
        return MinioPathUtils.getBaseUrl() + objectName;
    }
    
    /**
     * 上传MultipartFile文件到全局默认文件桶下的folder文件夹下
     *
     * @param objectName 文件名称, 如果要带文件夹请用 / 分割, 例如 /help/index.html
     * @param file       文件
     * @return 文件对应的URL
     */
    public String putObject(String objectName, MultipartFile file) {
        // 开始上传
        this.putMultipartFile(minioProperties.getBucket(), objectName, file);
        return MinioPathUtils.getBaseUrl() + objectName;
    }


    /**
     * 上传流到指定的文件桶下
     *
     * @param bucketName  桶名称
     * @param objectName  文件名称, 如果要带文件夹请用 / 分割, 例如 /help/index.html
     * @param stream      文件流
     * @param contentType 文件类型, 例如 image/jpeg: jpg图片格式, 详细可看: https://www.runoob.com/http/http-content-type.html
     * @return 文件对应的URL
     */
    public String putObject(String objectName, InputStream stream, String contentType) {
        // 开始上传
        this.putInputStream(minioProperties.getBucket(), objectName, stream, contentType);
        return MinioPathUtils.getBaseUrl() + objectName;
    }

    /**
     * 上传File文件到默认桶下
     *
     * @param objectName  文件名
     * @param file        文件
     * @param contentType 文件类型, 例如 image/jpeg: jpg图片格式, 详细可看: https://www.runoob.com/http/http-content-type.html
     * @return 文件对应的URL
     */
    public String putObject(String objectName, File file, String contentType) {
        // 开始上传
        this.putFile(minioProperties.getBucket(), objectName, file, contentType);
        return MinioPathUtils.getBaseUrl() + objectName;
    }

    /**
     * 判断文件是否存在
     *
     * @param objectName 文件名称, 如果要带文件夹请用 / 分割, 例如 /help/index.html
     * @return true存在, 反之
     */
    public Boolean checkFileIsExist(String objectName) {
        return this.checkFileIsExist(minioProperties.getBucket(), objectName);
    }

    /**
     * 判断文件夹是否存在
     *
     * @param folderName 文件夹名称
     * @return true存在, 反之
     */
    public Boolean checkFolderIsExist(String folderName) {
        return this.checkFolderIsExist(minioProperties.getBucket(), folderName);
    }

    /**
     * 判断文件是否存在
     *
     * @param bucketName 桶名称
     * @param objectName 文件名称, 如果要带文件夹请用 / 分割, 例如 /help/index.html
     * @return true存在, 反之
     */
    public Boolean checkFileIsExist(String bucketName, String objectName) {
        try {
            minioClient.statObject(
                StatObjectArgs.builder().bucket(bucketName).object(objectName).build()
            );
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 判断文件夹是否存在
     *
     * @param bucketName 桶名称
     * @param folderName 文件夹名称
     * @return true存在, 反之
     */
    public Boolean checkFolderIsExist(String bucketName, String folderName) {
        try {
            Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs
                    .builder()
                    .bucket(bucketName)
                    .prefix(folderName)
                    .recursive(false)
                    .build());
            for (Result<Item> result : results) {
                Item item = result.get();
                if (item.isDir() && folderName.equals(item.objectName())) {
                    return true;
                }
            }
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 根据文件全路径获取文件流
     *
     * @param objectName 文件名称
     * @return 文件流
     */
    public InputStream getObject(String objectName) {
        return this.getObject(minioProperties.getBucket(), objectName);
    }

    /**
     * 根据文件桶和文件全路径获取文件流
     *
     * @param bucketName 桶名称
     * @param objectName 文件名
     * @return 文件流
     */
    public InputStream getObject(String bucketName, String objectName) {
        try {
            return minioClient
                .getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
        } catch (Exception e) {
            throw new RuntimeException("根据文件名获取流失败!", e);
        }
    }
    
    /**
       * 断点下载
       *
       * @param bucketName bucket名称
       * @param objectName 文件名称
       * @param offset 起始字节的位置
       * @param length 要读取的长度
       * @return 流
       */
      public InputStream getObject(String bucketName, String objectName, long offset, long length)
          throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        return minioClient.getObject(
            GetObjectArgs.builder().bucket(bucketName).object(objectName).offset(offset).length(length)
                .build());
      }

    /**
     * 获取全部bucket
     *
     * @return 所有桶信息
     */
    public List<Bucket> getAllBuckets() {
        try {
            return minioClient.listBuckets();
        } catch (Exception e) {
            throw new RuntimeException("获取全部存储桶失败!", e);
        }
    }

    /**
     * 根据bucketName获取信息
     *
     * @param bucketName bucket名称
     * @return 单个桶信息
     */
    public Optional<Bucket> getBucket(String bucketName) {
        try {
            return minioClient.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
        } catch (Exception e) {
            throw new RuntimeException("根据存储桶名称获取信息失败!", e);
        }
    }

    /**
     * 根据bucketName删除信息
     *
     * @param bucketName bucket名称
     */
    public void removeBucket(String bucketName) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            throw new RuntimeException("根据存储桶名称删除桶失败!", e);
        }
    }

    /**
     * 删除文件
     *
     * @param objectName 文件名称
     */
    public boolean removeObject(String objectName) {
        try {
            this.removeObject(minioProperties.getBucket(), objectName);
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 删除文件
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     */
    public boolean removeObject(String bucketName, String objectName) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
        } catch (Exception e) {
            return false;
        }
        return true;
    }

    /**
     * 上传MultipartFile通用方法
     *
     * @param bucketName 桶名称
     * @param objectName 文件名
     * @param file       文件
     */
    private void putMultipartFile(String bucketName, String objectName, MultipartFile file) {
        InputStream stream = null;
        try {
            stream = file.getInputStream();
        } catch (IOException e) {
            throw new RuntimeException("文件流获取错误", e);
        }
        try {
            minioClient.putObject(
                PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .contentType(file.getContentType())
                    .stream(stream, stream.available(), -1)
                    .build()
            );
        } catch (Exception e) {
            throw new RuntimeException("文件流上传错误", e);
        }
    }

    /**
     * 上传InputStream通用方法
     *
     * @param bucketName 桶名称
     * @param objectName 文件名
     * @param stream     文件流
     */
    private void putInputStream(String bucketName, String objectName, InputStream stream, String contentType) {
        try {
            minioClient.putObject(
                PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .contentType(contentType)
                    .stream(stream, stream.available(), -1)
                    .build()
            );
        } catch (Exception e) {
            throw new RuntimeException("文件流上传错误", e);
        }
    }

    /**
     * 上传 bytes 通用方法
     *
     * @param bucketName 桶名称
     * @param objectName 文件名
     * @param bytes      字节编码
     */
    private void putBytes(String bucketName, String objectName, byte[] bytes, String contentType) {
        // 字节转文件流
        InputStream stream = new ByteArrayInputStream(bytes);
        try {
            minioClient.putObject(
                PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .contentType(contentType)
                    .stream(stream, stream.available(), -1)
                    .build()
            );
        } catch (Exception e) {
            throw new RuntimeException("文件流上传错误", e);
        }
    }

    /**
     * 上传 file 通用方法
     *
     * @param bucketName  桶名称
     * @param objectName  文件名
     * @param file        文件
     * @param contentType 文件类型, 例如 image/jpeg: jpg图片格式, 详细可看: https://www.runoob.com/http/http-content-type.html
     */
    private void putFile(String bucketName, String objectName, File file, String contentType) {
        try {
            FileInputStream fileInputStream = new FileInputStream(file);
            minioClient.putObject(
                PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .contentType(contentType)
                    .stream(fileInputStream, fileInputStream.available(), -1)
                    .build()
            );
        } catch (Exception e) {
            throw new RuntimeException("文件上传错误", e);
        }
    }

    /**
     * 获取文件信息, 如果抛出异常则说明文件不存在
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject
     */
    public StatObjectResponse getObjectInfo(String objectName) throws Exception {
        return minioClient.statObject(StatObjectArgs.builder().bucket(minioProperties.getBucket()).object(objectName).build());
    }

    /**
     * 获取文件外链
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @param expires    过期时间 <=7
     * @return url
     * @throws IOException 
     * @throws IllegalArgumentException 
     * @throws ServerException 
     * @throws XmlParserException 
     * @throws NoSuchAlgorithmException 
     * @throws InvalidResponseException 
     * @throws InternalException 
     * @throws InsufficientDataException 
     * @throws ErrorResponseException 
     * @throws InvalidKeyException 
     */
    public String getObjectURL(String bucketName, String objectName, Integer expires) throws InvalidKeyException, ErrorResponseException, InsufficientDataException, InternalException, InvalidResponseException, NoSuchAlgorithmException, XmlParserException, ServerException, IllegalArgumentException, IOException {
        IntFunction<Integer> integerIntFunction = (int i) -> {
            return Math.min(i, 7);
        };
        return minioClient.getPresignedObjectUrl(
            GetPresignedObjectUrlArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .expiry(integerIntFunction.apply(expires))
                .build());
    }

    /**
     * 根据文件前置查询文件
     *
     * @param bucketName bucket名称
     * @param prefix     前缀
     * @param recursive  是否递归查询
     * @return MinioItem 列表
     * @throws IOException 
     * @throws XmlParserException 
     * @throws ServerException 
     * @throws NoSuchAlgorithmException 
     * @throws InvalidResponseException 
     * @throws InternalException 
     * @throws InsufficientDataException 
     * @throws IllegalArgumentException 
     * @throws ErrorResponseException 
     * @throws JsonMappingException 
     * @throws InvalidKeyException 
     * @throws JsonParseException 
     */
    public List<Item> getAllObjectsByPrefix(String prefix, boolean recursive) throws JsonParseException, InvalidKeyException, JsonMappingException, ErrorResponseException, IllegalArgumentException, InsufficientDataException, InternalException, InvalidResponseException, NoSuchAlgorithmException, ServerException, XmlParserException, IOException {
        List<Item> list = new ArrayList<>();
        Iterable<Result<Item>> objectsIterator = minioClient.listObjects(
            ListObjectsArgs.builder().bucket(minioProperties.getBucket()).prefix(prefix)
                .recursive(recursive).build()
        );
        if (objectsIterator != null) {
            for (Result<Item> result : objectsIterator) {
                Item item = result.get();
                list.add(item);
            }
        }
        return list;
    }
    
      /**
       * 拷贝文件
       *
       * @param bucketName bucket名称
       * @param objectName 文件名称
       * @param srcBucketName 目标bucket名称
       * @param srcObjectName 目标文件名称
       */
      public ObjectWriteResponse copyObject(String bucketName, String objectName,
          String srcBucketName, String srcObjectName)
          throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
        return minioClient.copyObject(
            CopyObjectArgs.builder()
                .source(CopySource.builder().bucket(bucketName).object(objectName).build())
                .bucket(srcBucketName)
                .object(srcObjectName)
                .build());
      }

}

这样就可以在业务代码里注入使用MinioTemplate了,这里面只是封装了一些常用的方法,不够的可以根据官方api文档再进行封装

文中的对外访问链接可以在nginx上配置域名,指向minio的9000端口就可以了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容