配置类
package com.seliote.mlb.fs.config;
import com.seliote.mlb.common.config.PropertiesInjector;
import io.minio.BucketExistsArgs;
import io.minio.MinioClient;
import io.minio.errors.MinioException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
/**
* MinIO 配置类
*
* @author seliote
*/
@Slf4j
@Configuration
public class MinioConfig {
private final PropertiesInjector.Minio minioProp;
@Autowired
public MinioConfig(PropertiesInjector propertiesInjector) {
this.minioProp = propertiesInjector.getMinio();
}
/**
* MinioClient Bean
*
* @return MinioClient 对象
*/
@Bean
public MinioClient minioClient()
throws MinioException, IOException, NoSuchAlgorithmException, InvalidKeyException {
var client = MinioClient.builder()
.endpoint(minioProp.getEndpoint())
.credentials(minioProp.getAccessKey(), minioProp.getSecretKey())
.build();
// 检查 Bucket 是否存在
boolean found = client.bucketExists(BucketExistsArgs.builder()
.bucket(minioProp.getBucket())
.build());
if (!found) {
log.error("Bucket {} not found! Please create it first", minioProp.getBucket());
throw new IllegalStateException("Bucket not found");
}
log.info("Minio bucket: {}", minioProp.getBucket());
return client;
}
}
Service,这里是文件都不会很大的情况,为了避免不经意的句柄泄漏所以都采取了 byte[] 类型,可根据需要改为流
package com.seliote.mlb.fs.service;
import com.seliote.mlb.common.jsr303.minio.Catalog;
import com.seliote.mlb.common.jsr303.minio.Extension;
import com.seliote.mlb.common.jsr303.minio.Filename;
import com.seliote.mlb.fs.exception.MinioException;
import org.springframework.validation.annotation.Validated;
import javax.validation.constraints.NotNull;
/**
* Minio Service
*
* @author seliote
* @version 2021-07-02
*/
@Validated
public interface MinioService {
/**
* 上传文件
*
* @param catalog 文件分类
* @param extension 文件类型
* @param bytes 输入字节
* @return 上传文件返回的名称
* @throws MinioException 上传失败时抛出
*/
@Filename
String upload(@Catalog String catalog, @Extension String extension, @NotNull byte[] bytes)
throws MinioException;
/**
* 下载文件
*
* @param catalog 文件分类
* @param filename 上传文件返回的名称
* @return 文件字节数组
* @throws MinioException 下载失败时抛出
*/
@NotNull
byte[] download(@Catalog String catalog, @Filename String filename) throws MinioException;
}
Impl
package com.seliote.mlb.fs.service.impl;
import com.seliote.mlb.common.config.YmlConfig;
import com.seliote.mlb.fs.exception.MinioException;
import com.seliote.mlb.fs.service.MinioService;
import io.minio.GetObjectArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
/**
* Minio Service 实现
*
* @author seliote
* @version 2021-07-02
*/
@Slf4j
@Service
public class MinioServiceImpl implements MinioService {
// Minio 路径分隔符
private static final String MINIO_PATH_SEPARATOR = "/";
private final YmlConfig.Minio minio;
private final MinioClient minioClient;
@Autowired
public MinioServiceImpl(YmlConfig ymlConfig, MinioClient minioClient) {
this.minio = ymlConfig.getMinio();
this.minioClient = minioClient;
}
@Override
public String upload(String catalog, String extension, byte[] bytes) throws MinioException {
String filename = UUID.randomUUID().toString();
// 分为 26 * 26 目录存储,避免同级存在大量文件
String path = catalog + MINIO_PATH_SEPARATOR + filename.charAt(0) + MINIO_PATH_SEPARATOR
+ filename.charAt(1) + MINIO_PATH_SEPARATOR + filename + "." + extension;
try (var is = new ByteArrayInputStream(bytes)) {
minioClient.putObject(PutObjectArgs.builder()
.bucket(minio.getBucket())
.object(path)
.stream(is, -1, 1024 * 1024 * 10)
.build());
log.info("Upload file {}", path);
return filename;
} catch (io.minio.errors.MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException
exception) {
log.info("Failed upload file {}, {}", filename, exception.getMessage());
throw new MinioException(exception);
}
}
@Override
public byte[] download(String catalog, String filename) throws MinioException {
String path = catalog + MINIO_PATH_SEPARATOR + filename.charAt(0) + MINIO_PATH_SEPARATOR
+ filename.charAt(1) + MINIO_PATH_SEPARATOR + filename;
try (var is = minioClient.getObject(GetObjectArgs.builder()
.bucket(minio.getBucket())
.object(path)
.build())) {
log.info("Download file {}", path);
return is.readAllBytes();
} catch (io.minio.errors.MinioException | InvalidKeyException | IOException | NoSuchAlgorithmException
exception) {
log.info("Failed download file {}, {}", path, exception.getMessage());
throw new MinioException(exception);
}
}
}