Springboot整合minio组件-分布式文件存储

一、快速开始

Minlo说明:
  1. Minio是Apcche旗下的一款开源的轻量级文件服务器,基于对象存储,协议是基于Apache License v2.0,开源可用于商务。
  2. Minio主要用来存储非结构化的数据,类似文件,图片,照片,日志文件,各类备份文件等,按照官网描述,文件的大小从几KB到5TB。
  3. Minio提供了非常方便,友好的界面,并且文档也是非常丰富,具体可以参考它的文档:https://docs.min.io/cn/
  4. Minlo作用类似于FastDFS和阿里云的OSS进行对象存储
  5. 安装minlo服务器参考:https://blog.csdn.net/u010189683/article/details/108171562
1、添加依赖
xml 复制代码
<!--minio方案-->
<dependency>
	<groupId>io.minio</groupId>
	<artifactId>minio</artifactId>
	<version>7.0.2</version>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-configuration-processor</artifactId>
	<optional>true</optional>
</dependency>
2、添加配置项
yaml 复制代码
## minio配置 
minio:
   endpoint: http://192.168.179.131:9000/
   accessKey: admin
   secretKey: admin123456    
3、配置项和工具类
java 复制代码
@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {

	private String endpoint;
	private String accessKey;
	private String secretKey;

	@Bean
	public MinioClient getMinioClient() throws InvalidEndpointException, InvalidPortException {
		MinioClient minioClient = new MinioClient(endpoint, accessKey, secretKey);
		return minioClient;
	}

}
@Component
public class MinioUtil {
    
    @Value("${minio.endpoint}")
    private String endpoint;
    @Value("${minio.accessKey}")
    private String accessKey;
    @Value("${minio.secretKey}")
    private String secretKey;

    private static final int DEFAULT_EXPIRY_TIME = 7 * 24 * 3600;

	private static MinioClient minioClient;

    @Autowired
    @SneakyThrows
    public MinioClient setMinioClient(){
         MinioClient minioClient = new MinioClient(endpoint, accessKey, secretKey);
         return minioClient;
    }

	/**
	 * 检查存储桶是否存在
	 */
    @SneakyThrows
	public boolean bucketExists(String bucketName){
		boolean flag = minioClient.bucketExists(bucketName);
        return flag ? true : false;
	}

	/**
	 * 创建存储桶
	 */
    @SneakyThrows
	public boolean makeBucket(String bucketName) {
		boolean flag = bucketExists(bucketName);
        if(flag) return false;
        minioClient.makeBucket(bucketName);
        return true;
	}

	/**
	 * 列出所有存储桶名称
	 */
    @SneakyThrows
	public List<String> listBucketNames() {
		List<Bucket> bucketList = listBuckets();
        return bucketList.stream().map(item->bucket.name()).collect(Collector.toList())
	}

	/**
	 * 列出所有存储桶
	 */
    @SneakyThrows
	public List<Bucket> listBuckets() {
		return minioClient.listBuckets();
	}

	/**
	 * 删除存储桶
	 */
    @SneakyThrows
	public boolean removeBucket(String bucketName) {
		boolean flag = bucketExists(bucketName);
        if(flag) return false;
        Iterable<Result<Item>> myObjects = listObjects(bucketName);
        for (Result<Item> result : myObjects) {
            Item item = result.get();
            // 有对象文件,则删除失败
            if (item.size() > 0) {
                return false;
            }
        }
        // 删除存储桶,注意,只有存储桶为空时才能删除成功。
        minioClient.removeBucket(bucketName);
        flag = bucketExists(bucketName);
        if (!flag) {
            return true;
        }
	}

	/**
	 * 列出存储桶中的所有对象名称
	 */
    @SneakyThrows
	public List<String> listObjectNames(String bucketName) {
		List<String> listObjectNames = new ArrayList<>();
		boolean flag = bucketExists(bucketName);
		if (flag) {
			Iterable<Result<Item>> myObjects = listObjects(bucketName);
			for (Result<Item> result : myObjects) {
				Item item = result.get();
				listObjectNames.add(item.objectName());
			}
		}
		return listObjectNames;
	}

	/**
	 * 列出存储桶中的所有对象
	 */
    @SneakyThrows
	public Iterable<Result<Item>> listObjects(String bucketName)  {
		boolean flag = bucketExists(bucketName);
        return flag?minioClient.listObjects(bucketName):null;
	}

	/**
	 * 通过文件上传到对象
	 */
    @SneakyThrows
	public boolean putObject(String bucketName, String objectName, String fileName){
		boolean flag = bucketExists(bucketName);
		if (flag) {
			minioClient.putObject(bucketName, objectName, fileName, null);
			ObjectStat statObject = statObject(bucketName, objectName);
			if (statObject != null && statObject.length() > 0) {
				return true;
			}
		}
		return false;

	}

	/**
	 * 通过InputStream上传对象
	 */
    @SneakyThrows
	public boolean putObject(String bucketName, String objectName, InputStream stream) {
		boolean flag = bucketExists(bucketName);
		if (flag) {
			minioClient.putObject(bucketName, objectName, stream, new PutObjectOptions(stream.available(), -1));
			ObjectStat statObject = statObject(bucketName, objectName);
			if (statObject != null && statObject.length() > 0) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 以流的形式获取一个文件对象
	 */
    @SneakyThrows
	public InputStream getObject(String bucketName, String objectName){
		boolean flag = bucketExists(bucketName);
		if (flag) {
			ObjectStat statObject = statObject(bucketName, objectName);
			if (statObject != null && statObject.length() > 0) {
				InputStream stream = minioClient.getObject(bucketName, objectName);
				return stream;
			}
		}
		return null;
	}

	/**
	 * 以流的形式获取一个文件对象(断点下载)
	 */
    @SneakyThrows
	public InputStream getObject(String bucketName, String objectName, long offset, Long length){
		boolean flag = bucketExists(bucketName);
		if (flag) {
			ObjectStat statObject = statObject(bucketName, objectName);
			if (statObject != null && statObject.length() > 0) {
				InputStream stream = minioClient.getObject(bucketName, objectName, offset, length);
				return stream;
			}
		}
		return null;
	}

	/**
	 * 下载并将文件保存到本地
	 */
    @SneakyThrows
	public boolean getObject(String bucketName, String objectName, String fileName) {
		boolean flag = bucketExists(bucketName);
		if (flag) {
			ObjectStat statObject = statObject(bucketName, objectName);
			if (statObject != null && statObject.length() > 0) {
				minioClient.getObject(bucketName, objectName, fileName);
				return true;
			}
		}
		return false;
	}

	/**
	 * 删除一个对象
	 */
    @SneakyThrows
	public boolean removeObject(String bucketName, String objectName) {
		boolean flag = bucketExists(bucketName);
		if (flag) {
			minioClient.removeObject(bucketName, objectName);
			return true;
		}
		return false;
	}

	/**
	 * 删除指定桶的多个文件对象,返回删除错误的对象列表,全部删除成功,返回空列表
	 */
    @SneakyThrows
	public List<String> removeObject(String bucketName, List<String> objectNames){
		List<String> deleteErrorNames = new ArrayList<>();
		boolean flag = bucketExists(bucketName);
		if (flag) {
			Iterable<Result<DeleteError>> results = minioClient.removeObjects(bucketName, objectNames);
			for (Result<DeleteError> result : results) {
				DeleteError error = result.get();
				deleteErrorNames.add(error.objectName());
			}
		}
		return deleteErrorNames;
	}

	/**
	 * 生成一个给HTTP GET请求用的presigned URL。
	 * 浏览器/移动端的客户端可以用这个URL进行下载,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。
	 */
    @SneakyThrows
	public String presignedGetObject(String bucketName, String objectName, Integer expires) {
		boolean flag = bucketExists(bucketName);
        return bucketExists(bucketName) ? minioClient.presignedGetObject(bucketName, objectName, expires):null;
	}

	/**
	 * 生成一个给HTTP PUT请求用的presigned URL。
	 * 浏览器/移动端的客户端可以用这个URL进行上传,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。
	 */
    @SneakyThrows
	public String presignedPutObject(String bucketName, String objectName, Integer expires) {
		return bucketExists(bucketName) ? minioClient.presignedPutObject(bucketName, objectName, expires):null;
	}

	/**
	 * 获取对象的元数据
	 */
    @SneakyThrows
	public ObjectStat statObject(String bucketName, String objectName){
        return bucketExists(bucketName) ? minioClient.statObject(bucketName, objectName) : null;
	}

	/**
	 * 文件访问路径
	 */
    @SneakyThrows
	public String getObjectUrl(String bucketName, String objectName) {
		return bucketExists(bucketName) ? minioClient.getObjectUrl(bucketName, objectName) : "";
	}
}
相关推荐
wb043072017 小时前
使用 Java 开发 MCP 服务并发布到 Maven 中央仓库完整指南
java·开发语言·spring boot·ai·maven
nbwenren8 小时前
Springboot中SLF4J详解
java·spring boot·后端
helx829 小时前
SpringBoot中自定义Starter
java·spring boot·后端
rleS IONS10 小时前
SpringBoot获取bean的几种方式
java·spring boot·后端
lifewange10 小时前
Go语言-开源编程语言
开发语言·后端·golang
白毛大侠10 小时前
深入理解 Go:用户态和内核态
开发语言·后端·golang
R***z10111 小时前
Spring Boot 整合 MyBatis 与 PostgreSQL 实战指南
spring boot·postgresql·mybatis
王码码203511 小时前
Go语言中的数据库操作:从sqlx到ORM
后端·golang·go·接口
星辰_mya12 小时前
雪花算法和时区的关系
数据库·后端·面试·架构师
赵丙双12 小时前
spring boot AutoConfiguration.replacements 文件的作用
java·spring boot