Bootstrap

框架集成Minio(内含Minio工具类以及mc突破七天限制)

文章目录

1.Docker安装Minio

1.拉取镜像
docker pull minio/minio:RELEASE.2024-11-07T00-52-20Z
docker pull minio/minio
2.查看镜像

CleanShot 2024-11-12 at 16.21.05@2x

3.创建环境变量文件
vim /etc/default/minio
# 用户名和密码
MINIO_ROOT_USER=myminioadmin
MINIO_ROOT_PASSWORD=myminioadmin

# minio容器内存储数据的路径
MINIO_VOLUMES="/mnt/data"
4.启动
docker run -dt                                  \
  -p 9000:9000 -p 9001:9001                     \
  -v /opt/minio/data:/mnt/data                  \
  -v /etc/default/minio:/etc/config.env         \
  -e "MINIO_CONFIG_ENV_FILE=/etc/config.env"    \
  --name "minio_local"                          \
  afadd2395ca6 server --console-address ":9001"

CleanShot 2024-11-12 at 16.41.09@2x

CleanShot 2024-11-12 at 16.41.17@2x

CleanShot 2024-11-12 at 18.04.32@2x

CleanShot 2024-11-12 at 18.04.39@2x

CleanShot 2024-11-12 at 18.04.50@2x

5.查看是否启动成功

CleanShot 2024-11-12 at 18.14.56@2x

6.开启9000和9001端口
1.宝塔开启
systemctl start firewalld && firewall-cmd --permanent --add-port=9000/tcp && firewall-cmd --reload && firewall-cmd --query-port=9000/tcp
systemctl start firewalld && firewall-cmd --permanent --add-port=9001/tcp && firewall-cmd --reload && firewall-cmd --query-port=9001/tcp
2.安全组开启

CleanShot 2024-11-12 at 18.20.56@2x

7.访问测试

http://62.225.1.120:9001

2.基本使用

1.创建一个桶

CleanShot 2024-11-12 at 18.31.30@2x

CleanShot 2024-11-12 at 18.31.52@2x

2.上传文件

CleanShot 2024-11-12 at 18.32.26@2x

CleanShot 2024-11-12 at 18.35.43@2x

3.创建访问密钥

CleanShot 2024-11-12 at 18.53.55@2x

CleanShot 2024-11-12 at 18.54.29@2x

3.minio快速入门

1.创建模块

CleanShot 2024-11-12 at 18.45.01@2x

2.引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sunxiansheng</groupId>
    <artifactId>minio-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.4.2</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- minio -->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.5.13</version>
        </dependency>
    </dependencies>

</project>
3.创建启动类
package com.sunxiansheng.minio;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Description: Minio启动类
 *
 * @Author sun
 * @Create 2024/11/12 18:47
 * @Version 1.0
 */
@SpringBootApplication
public class MinioApplication {
    public static void main(String[] args) {
        SpringApplication.run(MinioApplication.class, args);
    }
}

CleanShot 2024-11-12 at 18.49.26@2x

4.文件上传入门案例
package com.sunxiansheng.minio;

import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.UploadObjectArgs;
import io.minio.errors.MinioException;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class FileUploader {

    public static void main(String[] args)
            throws IOException, NoSuchAlgorithmException, InvalidKeyException {
        try {
            // 使用 MinIO 服务器地址和密钥创建 MinioClient
            MinioClient minioClient =
                    MinioClient.builder()
                            .endpoint("http://ip:9000")
                            .credentials("sssss", "sssss")
                            .build();

            // 检查是否存在存储桶 'test'
            boolean found =
                    minioClient.bucketExists(BucketExistsArgs.builder().bucket("test").build());
            if (!found) {
                // 如果不存在,则创建存储桶 'test'
                minioClient.makeBucket(MakeBucketArgs.builder().bucket("test").build());
            } else {
                System.out.println("Bucket 'test' already exists.");
            }

            // 上传文件 '/Users/sunxiansheng/Desktop/temp.txt' 到 'test' 存储桶中
            minioClient.uploadObject(
                    UploadObjectArgs.builder()
                            .bucket("test")
                            .object("temp.txt")
                            .filename("/Users/sunxiansheng/Desktop/temp.txt")
                            .build());
            System.out.println(
                    "'/Users/sunxiansheng/Desktop/temp.txt' is successfully uploaded as "
                            + "object 'temp.txt' to bucket 'test'.");
        } catch (MinioException e) {
            System.out.println("Error occurred: " + e);
            System.out.println("HTTP trace: " + e.httpTrace());
        }
    }
}

4.Minio常用API

1.官网

https://min.io/docs/minio/linux/developers/java/API.html

CleanShot 2024-11-12 at 19.11.30@2x

2.MinIO 客户端生成器
1.目录

CleanShot 2024-11-12 at 19.54.36@2x

2.MinioProperties.java
package com.sunxiansheng.minio.config.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * Description: Minio配置
 *
 * @Author sun
 * @Create 2024/11/12 19:15
 * @Version 1.0
 */
@Component
@ConfigurationProperties(prefix = "minio")
@Data
public class MinioProperties {

    /**
     * minio服务地址
     */
    private String endpoint;
    /**
     * minio服务用户名
     */
    private String accessKey;
    /**
     * minio服务密码
     */
    private String secretKey;
    /**
     * minio服务桶名称
     */
    private String bucketName = "defaultBucket";
}
3.MinioConfiguration.java
package com.sunxiansheng.minio.config;

import com.sunxiansheng.minio.config.properties.MinioProperties;
import io.minio.MinioClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;

/**
 * Description: Minio客户端配置
 *
 * @Author sun
 * @Create 2024/11/12 19:15
 * @Version 1.0
 */
@Configuration
@EnableConfigurationProperties({MinioProperties.class}) // 启用配置类
public class MinioConfiguration {

    @Resource
    private MinioProperties minioProperties;

    /**
     * 注入MinioClient
     *
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    MinioClient minioClient() {
        return MinioClient.builder()
                .endpoint(minioProperties.getEndpoint())
                .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
                .build();
    }
}
4.application.yml 配置文件编写
minio:
  endpoint: http://ip:9000
  accessKey: siSdfsdwdfdsfadsfFryK53Dz7g
  secretKey: siSdfsdwdfdsfadsfFryK53Dz7g
  bucketName: test
5.MinioController.java 测试使用客户端生成器进行文件上传
package com.sunxiansheng.minio.controller;

import io.minio.*;
import io.minio.errors.MinioException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.sunxiansheng.minio.config.properties.MinioProperties;

import javax.annotation.Resource;

/**
 * Description: Minio控制器
 *
 * @Author sun
 * @Create 2024/11/12 19:31
 * @Version 1.0
 */
@RestController
public class MinioController {

    /**
     * 注入MinioClient
     */
    @Resource
    private MinioClient minioClient;

    /**
     * 注入MinioProperties
     */
    @Resource
    private MinioProperties minioProperties;

    @RequestMapping("/test")
    public String test() {
        return "Hello Minio!";
    }

    @RequestMapping("/uploadFile")
    public String uploadFile() throws Exception {
        // 获取桶名
        String bucketName = minioProperties.getBucketName();
        try {
            // 检查是否存在存储桶 'test'
            boolean found =
                    minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!found) {
                // 如果不存在,则创建存储桶 'test'
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            } else {
                System.out.println("Bucket 'test' already exists.");
            }

            // 上传文件 '/Users/sunxiansheng/Desktop/temp.txt' 到 'test' 存储桶中
            minioClient.uploadObject(
                    UploadObjectArgs.builder()
                            .bucket(bucketName)
                            .object("temp2.txt")
                            .filename("/Users/sunxiansheng/Desktop/temp.txt")
                            .build());
        } catch (MinioException e) {
            System.out.println("Error occurred: " + e);
            System.out.println("HTTP trace: " + e.httpTrace());
        }
        return "'/Users/sunxiansheng/Desktop/temp.txt' is successfully uploaded as \"\n" +
                "                                + \"object 'temp.txt' to bucket 'test'.";
    }
}
3.检查桶是否存在
1.代码
    /**
     * 检查存储桶是否存在
     *
     * @param bucketName
     * @return
     */
    @RequestMapping("/bucketExists")
    public boolean bucketExists(@RequestParam String bucketName) {
        try {
            return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
2.结果

CleanShot 2024-11-12 at 20.07.05@2x

4.列出所有水桶的信息
1.代码
    /**
     * 列出所有存储桶
     *
     * @return
     */
    @RequestMapping("/listBuckets")
    public List<String> listBuckets() {
        try {
            List<Bucket> buckets = minioClient.listBuckets();
            List<String> res = buckets.stream().map(
                    Bucket::name
            ).collect(Collectors.toList());
            return res;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
2.结果

CleanShot 2024-11-12 at 20.16.52@2x

5.创建桶
1.代码
    /**
     * 创建桶
     *
     * @param bucketName
     * @return
     */
    @RequestMapping("/makeBucket")
    public String makeBucket(@RequestParam String bucketName) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            return "Bucket " + bucketName + " created successfully!";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "Bucket " + bucketName + " created failed!";
    }
2.结果

CleanShot 2024-11-12 at 20.23.31@2x

6.删除桶
1.代码
/**
 * 删除桶
 *
 * @param bucketName
 * @return
 */
@RequestMapping("/removeBucket")
public String removeBucket(@RequestParam String bucketName) {
    try {
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
        return "Bucket " + bucketName + " removed successfully!";
    } catch (Exception e) {
        e.printStackTrace();
    }
    return "Bucket " + bucketName + " removed failed!";
}
2.结果

7.下载对象到指定位置
1.代码
/**
 * 下载对象到指定位置
 */
@RequestMapping("/downloadObject")
public String downloadObject() {
    try {
        // 下载文件
        minioClient.downloadObject(
                DownloadObjectArgs.builder()
                        .bucket("test")
                        .object("temp.txt")
                        .filename("/Users/sunxiansheng/Desktop/downTemp.txt")
                        .build());
        return "Download object success!";
    } catch (Exception e) {
        e.printStackTrace();
    }
    return "Download object failed!";
}
2.结果

CleanShot 2024-11-12 at 20.42.17@2x

CleanShot 2024-11-12 at 20.42.21@2x

8.获取对象的预签名URL(是临时的)
1.代码
/**
 * 获取对象的预签名URL
 *
 * @return
 */
@RequestMapping("/getPresignedObjectUrl")
public String getPresignedObjectUrl() {
    try {
        Map<String, String> reqParams = new HashMap<String, String>();
        reqParams.put("response-content-type", "image/jpeg");
        String url =
                minioClient.getPresignedObjectUrl(
                        GetPresignedObjectUrlArgs.builder()
                                .method(Method.GET)
                                .bucket("test")
                                .object("idea-background.jpg")
                                .extraQueryParams(reqParams)
                                .build());
        return url;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
9.将给定数据流作为对象上传至数据桶
1.代码
    /**
     * 文件上传
     */
    @RequestMapping("/putObject")
    public String putObject(@RequestParam MultipartFile file, @RequestParam String bucket) {
        // 获取文件名
        String fileName = file.getOriginalFilename();
        // 获取输入流
        try {
            InputStream inputStream = file.getInputStream();
            // 获取当前日期,构建文件夹路径
            String dateFolder = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
            // 使用 UUID 生成唯一标识,防止重复
            String uniqueName = UUID.randomUUID().toString();
            // 构造对象名称:日期路径 + 唯一标识 + 文件名
            String objectName = dateFolder + "/" + uniqueName + "-" + fileName;
            // 获取文件的 MIME 类型,如果不确定,则默认设置为 "application/octet-stream"
            String contentType = file.getContentType() != null ? file.getContentType() : "application/octet-stream";
            // 执行上传操作,不指定大小并分块上传,假设块大小为 10 MB
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucket)
                            .object(objectName)
                            .stream(inputStream, -1, 10 * 1024 * 1024)  // 未知大小,使用 10 MB 分块上传
                            .contentType(contentType)                    // 设置内容类型
                            .build()
            );
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return "上传成功" + fileName;
    }
2.结果

CleanShot 2024-11-12 at 22.17.02@2x

CleanShot 2024-11-12 at 22.16.53@2x

CleanShot 2024-11-12 at 22.17.14@2x

CleanShot 2024-11-12 at 22.17.22@2x

10.删除指定前缀的所有对象(文件或文件夹)
1.代码
    /**
     * 删除指定前缀的所有对象(文件或文件夹)
     *
     * @param bucket     桶名称
     * @param prefix     对象前缀(文件夹路径或文件名)
     * @return 删除结果
     */
    @RequestMapping("/removeObjectOrFolder")
    public String removeObjectOrFolder(@RequestParam String bucket, @RequestParam String prefix) {
        try {
            // 列出该前缀下的所有对象
            Iterable<Result<Item>> objects = minioClient.listObjects(
                    ListObjectsArgs.builder()
                            .bucket(bucket)
                            .prefix(prefix)   // 使用指定前缀
                            .recursive(true)  // 递归列出所有子对象
                            .build());

            // 遍历并删除前缀下的所有对象
            for (Result<Item> result : objects) {
                String objectName = result.get().objectName();
                minioClient.removeObject(
                        RemoveObjectArgs.builder()
                                .bucket(bucket)
                                .object(objectName)
                                .build()
                );
            }
            return "All objects under " + prefix + " removed successfully!";
        } catch (Exception e) {
            e.printStackTrace();
            return "Failed to remove objects under " + prefix;
        }
    }
2.结果

CleanShot 2024-11-12 at 22.36.36@2x

11.Docker安装miniomc突破7天限制
1.拉取镜像
docker pull minio/mc:RELEASE.2023-11-15T22-45-58Z.fips
2.运行容器
docker run -it --entrypoint=/bin/sh minio/mc:RELEASE.2023-11-15T22-45-58Z.fips
3.进行配置
1.格式
mc config host add <ALIAS> <YOUR-S3-ENDPOINT> <YOUR-ACCESS-KEY> <YOUR-SECRET-KEY>
2.具体
mc config host add minio http://ip:9000 siSwOw0yaxFryK53Dz7g siSwOw0yaxFryK53Dz7g
3.查看所有桶
mc ls minio

CleanShot 2024-11-12 at 22.52.14@2x

4.将桶设置为公开可读
mc anonymous set download minio/桶
mc anonymous set download minio/test

CleanShot 2024-11-12 at 22.53.08@2x

12.生成预览链接和下载链接(永久)
1.代码
@RequestMapping("/generateDownloadLink")
public String generateDownloadLink(String bucket, String objectName) {
    String endpoint = "http://ip:9000";  // MinIO 服务器地址
    // 设置文件的下载链接
    return endpoint + "/" + bucket + "/" + objectName + "?response-content-disposition=attachment";
}

@RequestMapping("/generatePreviewLink")
public String generatePreviewLink(String bucket, String objectName) {
    String endpoint = "http://ip:9000";  // MinIO 服务器地址
    // 返回文件的预览链接
    return endpoint + "/" + bucket + "/" + objectName;
}
2.结果

5.封装Minio模块

1.创建模块

CleanShot 2024-11-12 at 22.57.48@2x

2.引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.sunxiansheng</groupId>
        <artifactId>sunrays-common</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>common-minio-starter</artifactId>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <!-- 排除logging,防止日志冲突 -->
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-logging</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <!-- minio -->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
        </dependency>
        <!-- okhttp必须升级到这个版本 -->
        <dependency>
            <groupId>com.squareup.okhttp3</groupId>
            <artifactId>okhttp</artifactId>
            <version>4.11.0</version>
        </dependency>
    </dependencies>
</project>
3.自动配置读取配置
1.目录

CleanShot 2024-11-12 at 23.26.57@2x

2.MinioProperties.java
package com.sunxiansheng.minio.config.properties;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * Description: Minio配置
 *
 * @Author sun
 * @Create 2024/11/12 23:15
 * @Version 1.0
 */
@Component
@ConfigurationProperties(prefix = "minio")
@Data
public class MinioProperties {

    /**
     * minio服务地址
     */
    private String endpoint;
    /**
     * minio服务用户名
     */
    private String accessKey;
    /**
     * minio服务密码
     */
    private String secretKey;
    /**
     * minio服务桶名称
     */
    private String bucketName = "defaultBucket";
}
3.MinioAutoConfiguration.java
package com.sunxiansheng.minio.config;

import com.sunxiansheng.minio.config.properties.MinioProperties;
import io.minio.MinioClient;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Description: Minio自动配置类
 *
 * @Author sun
 * @Create 2024/11/12 23:14
 * @Version 1.0
 */
@Configuration
@EnableConfigurationProperties({MinioProperties.class}) // 启用配置类
public class MinioAutoConfiguration {

    /**
     * 注入MinioClient
     *
     * @return
     */
    @Bean
    @ConditionalOnMissingBean
    MinioClient minioClient(MinioProperties minioProperties) {
        return MinioClient.builder()
                .endpoint(minioProperties.getEndpoint())
                .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
                .build();
    }
}
4.spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.sunxiansheng.minio.config.MinioAutoConfiguration
4.测试
1.创建测试模块

CleanShot 2024-11-12 at 23.29.57@2x

2.引入依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.sunxiansheng</groupId>
        <artifactId>sunrays-demo</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>common-minio-starter-demo</artifactId>

    <dependencies>
        <!-- common-minio-starter -->
        <dependency>
            <groupId>com.sunxiansheng</groupId>
            <artifactId>common-minio-starter</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

</project
3.application.yml
minio:
  endpoint: http://ip:9000
  accessKey: siSwOw0yaxFryK53Dz7g
  secretKey: siSwOw0yaxFryK53Dz7g
  bucketName: test
4.启动类 MinioApplication.java
package com.sunxiansheng.minio;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * Description: Minio启动类
 *
 * @Author sun
 * @Create 2024/11/12 23:31
 * @Version 1.0
 */
@SpringBootApplication
public class MinioApplication {

    public static void main(String[] args) {
        SpringApplication.run(MinioApplication.class, args);
    }
}
5.MinioController.java
package com.sunxiansheng.minio.controller;

import com.sunxiansheng.minio.config.properties.MinioProperties;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * Description: Minio测试Controller
 *
 * @Author sun
 * @Create 2024/11/12 23:34
 * @Version 1.0
 */
@RestController
public class MinioController {

    @Resource
    private MinioProperties minioProperties;

    @RequestMapping("/testMinioProperties")
    public MinioProperties testMinioProperties() {
        return minioProperties;
    }
}
6.结果
5.Minio工具类
1.MinioUtil.java
package com.sunxiansheng.minio.utils;

import com.sunxiansheng.minio.config.properties.MinioProperties;
import io.minio.*;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * Description: Minio工具类
 *
 * @Author sun
 * @Create 2024/11/13 09:49
 * @Version 1.0
 */
@Component
public class MinioUtil {

    @Resource
    private MinioClient minioClient;

    @Resource
    private MinioProperties minioProperties;

    /**
     * 检查存储桶是否存在
     *
     * @param bucketName
     * @return
     */
    public boolean bucketExists(String bucketName) {
        try {
            return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            throw new RuntimeException("检查存储桶是否存在失败", e);
        }
    }

    /**
     * 列出所有存储桶的名字
     *
     * @return
     */
    public List<String> listBucketNames() {
        try {
            return minioClient.listBuckets().stream().map(Bucket::name).collect(Collectors.toList());
        } catch (Exception e) {
            throw new RuntimeException("列出所有存储桶的名字失败", e);
        }
    }

    /**
     * 根据名字创建存储桶
     *
     * @param bucketName
     */
    public void makeBucket(String bucketName) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            throw new RuntimeException("创建存储桶失败", e);
        }
    }

    /**
     * 根据名字移除一个空桶
     *
     * @param bucketName
     */
    public void removeBucket(String bucketName) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            throw new RuntimeException("移除存储桶失败", e);
        }
    }

    /**
     * 下载对象到指定位置
     *
     * @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());
        } catch (Exception e) {
            throw new RuntimeException("下载对象失败", e);
        }
    }

    /**
     * 文件上传并返回预览url和下载url
     *
     * @param file
     * @param bucketName
     * @return 第一个元素为预览url,第二个元素为下载url
     */
    public List<String> putObject(MultipartFile file, String bucketName) {
        try {
            // 获取文件名
            String fileName = file.getOriginalFilename();
            // 获取文件输入流
            InputStream inputStream = file.getInputStream();
            // 获取当前日期,构建文件夹路径
            String dateFolder = new SimpleDateFormat("yyyy/MM/dd").format(new Date());
            // 使用 UUID 生成唯一标识,防止重复
            String uniqueName = UUID.randomUUID().toString();
            // 构造对象名称:日期路径 + 唯一标识 + 文件名
            String objectName = dateFolder + "/" + uniqueName + "-" + fileName;
            // 获取文件的 MIME 类型,如果不确定,则默认设置为 "application/octet-stream"
            String contentType = file.getContentType() != null ? file.getContentType() : "application/octet-stream";
            // 执行上传操作,不指定大小并分块上传,块大小为 10 MB
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .stream(inputStream, -1, 10 * 1024 * 1024)
                            .contentType(contentType)
                            .build()
            );
            // 获取预览url
            String previewUrl = generatePreviewLink(bucketName, objectName);
            // 获取下载url
            String downloadUrl = generateDownloadLink(bucketName, objectName);
            return Arrays.asList(previewUrl, downloadUrl);
        } catch (Exception e) {
            throw new RuntimeException("上传对象失败", e);
        }
    }

    /**
     * 删除指定前缀的所有对象(文件或文件夹)
     *
     * @param bucketName     桶名称
     * @param prefix     对象前缀(文件夹路径或文件名)
     * @return 删除结果
     */
    public String removeObjectOrFolder(String bucketName, String prefix) {
        try {
            // 递归列出该前缀下的所有对象
            Iterable<Result<Item>> objects = minioClient.listObjects(
                    ListObjectsArgs.builder()
                            .bucket(bucketName)
                            .prefix(prefix)
                            .recursive(true)
                            .build());

            // 遍历并删除前缀下的所有对象
            for (Result<Item> result : objects) {
                String objectName = result.get().objectName();
                minioClient.removeObject(
                        RemoveObjectArgs.builder()
                                .bucket(bucketName)
                                .object(objectName)
                                .build()
                );
            }
            return "All objects under " + prefix + " removed successfully!";
        } catch (Exception e) {
            e.printStackTrace();
            return "Failed to remove objects under " + prefix;
        }
    }

    /**
     * 获取下载url
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public String generateDownloadLink(String bucketName, String objectName) {
        String endpoint = minioProperties.getEndpoint();
        // 设置文件的下载链接
        return String.format("%s/%s/%s?response-content-disposition=attachment", endpoint, bucketName, objectName);
    }

    /**
     * 获取预览url
     *
     * @param bucketName
     * @param objectName
     * @return
     */
    public String generatePreviewLink(String bucketName, String objectName) {
        String endpoint = minioProperties.getEndpoint();
        // 返回文件的预览链接
        return String.format("%s/%s/%s", endpoint, bucketName, objectName);
    }
}
2.MinioAutoConfiguration.java 注入工具类
/**
 * 注入MinioUtil
 *
 * @return
 */
@Bean
@ConditionalOnMissingBean
MinioUtil minioUtil() {
    return new MinioUtil();
}

CleanShot 2024-11-13 at 10.46.18@2x

3.MinioController.java 测试
package com.sunxiansheng.minio.controller;

import com.sunxiansheng.minio.utils.MinioUtil;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.List;

/**
 * Description: Minio测试Controller
 *
 * @Author sun
 * @Create 2024/11/12 23:34
 * @Version 1.0
 */
@RestController
public class MinioController {

    @Resource
    private MinioUtil minioUtil;

    /**
     * 检查存储桶是否存在
     */
    @GetMapping("/bucketExists")
    public boolean bucketExists(@RequestParam String bucketName) {
        return minioUtil.bucketExists(bucketName);
    }

    /**
     * 列出所有存储桶的名字
     */
    @GetMapping("/listBucketNames")
    public List<String> listBucketNames() {
        return minioUtil.listBucketNames();
    }

    /**
     * 创建存储桶
     */
    @PostMapping("/makeBucket")
    public String makeBucket(@RequestParam String bucketName) {
        minioUtil.makeBucket(bucketName);
        return "Bucket " + bucketName + " created successfully!";
    }

    /**
     * 删除空的存储桶
     */
    @DeleteMapping("/removeBucket")
    public String removeBucket(@RequestParam String bucketName) {
        minioUtil.removeBucket(bucketName);
        return "Bucket " + bucketName + " removed successfully!";
    }

    /**
     * 上传文件并返回预览和下载链接
     */
    @PostMapping("/upload")
    public List<String> uploadFile(@RequestParam MultipartFile file, @RequestParam String bucketName) {
        return minioUtil.putObject(file, bucketName);
    }

    /**
     * 下载文件到指定路径
     */
    @GetMapping("/download")
    public String downloadFile(@RequestParam String bucketName,
                               @RequestParam String objectName,
                               @RequestParam String fileName) {
        minioUtil.downloadObject(bucketName, objectName, fileName);
        return "File " + objectName + " downloaded to " + fileName;
    }

    /**
     * 删除文件或文件夹
     */
    @DeleteMapping("/removeObject")
    public String removeObjectOrFolder(@RequestParam String bucketName, @RequestParam String prefix) {
        return minioUtil.removeObjectOrFolder(bucketName, prefix);
    }
}
;