在springboot中使用Minio8

在springboot中使用Minio(8)

关于Minio

Minio的介绍,安装,以及基本维护,可以参考我以前的帖子 https://springboot.io/t/topic/2090。当时Java的sdk版本是:7.0.2,现在sdk升级到8了,有些API有些变化,主要还是规范了方法的参数。

Maven

<!-- https://mvnrepository.com/artifact/io.minio/minio -->
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.0.3</version>
</dependency>

配置

yml中配置基本信息

#--------------
# minio 服务
#--------------
minio:
  endpoint: https://127.0.0.1:9000
  access-key: admin
  secret-key: 123456
  bucket: bucket
  gateway: ${minio.endpoint}/${minio.bucket}

自定义配置类

package io.springboot.minio;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.ConstructorBinding;

/**
 * 
 * minio配置
 * 
 * @author KevinBlandy
 *
 */
@ConfigurationProperties(prefix = "minio")
@ConstructorBinding
public class MinioConfig {

	public final String endpoint;
	public final String accessKey;
	public final String secretKey;
	public final String bucket;
	public final String gateway;

	public MinioConfig(String endpoint, String accessKey, String secretKey, String bucket, String gateway) {
		super();
		this.endpoint = endpoint;
		this.accessKey = accessKey;
		this.secretKey = secretKey;
		this.bucket = bucket;
		this.gateway = gateway;
	}

	@Override
	public String toString() {
		return "MinioConfig [endpoint=" + endpoint + ", accessKey=" + accessKey + ", secretKey=" + secretKey
				+ ", bucket=" + bucket + ", gateway=" + gateway + "]";
	}
}

在主函数类添加注解,指定配置类所在的包

@ConfigurationPropertiesScan(basePackages = { "io.springboot.minio" })

MinioService

package io.springboot.minio;

import java.time.LocalDate;
import java.util.LinkedList;
import java.util.List;
import java.util.UUID;

import org.springframework.web.multipart.MultipartFile;

import io.minio.CopyObjectArgs;
import io.minio.CopySource;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import io.springboot.spring.SpringHelper;

public class MinioService {
	/**
	 * url分隔符
	 */
	public static final String URI_DELIMITER = "/";

	
	/**
	 * Minio
	 */
	private static volatile MinioConfig minioConfig;
	
	/**
	 * 上传文件
	 * @param multipartFile
	 * @return
	 */
	public static String putObject (MultipartFile multipartFile) {
		return putObject(new MultipartFile[] {multipartFile}).get(0);
	}
	
	/**
	 * 上传文件
	 * @param multipartFiles
	 * @return
	 */
	public static List<String> putObject(MultipartFile ...multipartFiles) {
		try {
			
			MinioConfig minioConfig = minioConfig();

			MinioClient minioClient = MinioClient.builder().endpoint(minioConfig.endpoint)
					.credentials(minioConfig.accessKey, minioConfig.secretKey)
					.build();

			List<String> retVal = new LinkedList<>(); 

			String[] folders = getDateFolder();

			for (MultipartFile multipartFile : multipartFiles) {
				
				// UUID重命名
				String fileName = UUID.randomUUID().toString().replace("-", "") + "." + getSuffix(multipartFile.getOriginalFilename());

				// 年/月/日/file
				String finalPath = new StringBuilder(String.join(URI_DELIMITER, folders)) 
									.append(URI_DELIMITER)
									.append(fileName).toString();

				minioClient.putObject(PutObjectArgs.builder()
						.stream(multipartFile.getInputStream(), multipartFile.getSize(),PutObjectArgs.MIN_MULTIPART_SIZE)
						.object(finalPath)
						.contentType(multipartFile.getContentType())
						.bucket(minioConfig.bucket)
						.build());

				retVal.add(gateway(finalPath));
			}
			return retVal;
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 复制文件
	 * @param source
	 * @param target
	 */
	public static void copy(String source, String target) {
		
		MinioConfig minioConfig = minioConfig();
		
		MinioClient minioClient = MinioClient.builder().endpoint(minioConfig.endpoint)
				.credentials(minioConfig.accessKey, minioConfig.secretKey)
				.build();
		try {
			minioClient.copyObject(CopyObjectArgs.builder()
									.bucket(minioConfig.bucket)
									.object(target)
									.source(CopySource.builder()
											.bucket(minioConfig.bucket)
											.object(source)
											.build())
									.build());
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 删除文件
	 * @param object
	 */
	public static void delete (String object) {
		
		MinioConfig minioConfig = minioConfig();
		
		MinioClient minioClient = MinioClient.builder().endpoint(minioConfig.endpoint)
				.credentials(minioConfig.accessKey, minioConfig.secretKey)
				.build();
		try {
			minioClient.removeObject(RemoveObjectArgs.builder()
					.bucket(minioConfig.bucket)
					.object(object)
					.build());
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 获取访问网关
	 * @param path
	 * @return
	 */
	protected static String gateway(String path) {
		String gateway = minioConfig().gateway;
		if (!gateway.endsWith(URI_DELIMITER)) {
			gateway += URI_DELIMITER;
		}
		return gateway + path;
	}
	
	/**
	 * 获取文件后缀
	 * @param fileName
	 * @return
	 */
	protected static String getSuffix(String fileName) {
		int index = fileName.lastIndexOf(".");
		if (index != -1) {
			String suffix = fileName.substring(index + 1);
			if (!suffix.isEmpty()) {
				return suffix;
			}
		}
		throw new IllegalArgumentException("非法文件名称:"  + fileName);
	}

	/**
	 * 获取年月日[2020, 09, 01]
	 * @return
	 */
	protected static String[] getDateFolder() {
		String[] retVal = new String[3];

		LocalDate localDate = LocalDate.now();
		retVal[0] = localDate.getYear() + "";

		int month = localDate.getMonthValue();
		retVal[1] = month < 10 ? "0" + month : month + "";

		int day = localDate.getDayOfMonth();
		retVal[2] = day < 10 ? "0" + day : day + "";

		return retVal;
	}
	
	/**
	 * 获取minio配置
	 * @return
	 */
	protected static MinioConfig minioConfig() {
		if (minioConfig == null) {
			synchronized (MinioService.class) {
				if (minioConfig == null) {
					/**
					 * 从IOC中获取到配置项
					 */
					minioConfig = SpringHelper.applicationContext.getBean(MinioConfig.class);
				}
			}
		}
		return minioConfig;
	}
}