MinIO(对象存储服务)
简介
MinIO基于Apache License v2.0开源协议的对象存储服务,可以做为云存储的解决方案用来保存海量的图片,视频,文档。由于采用Golang实现,服务端可以工作在Windows,Linux, OS X和FreeBSD上。配置简单,基本是复制可执行程序,单行命令可以运行起来。
MinIO兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。
入门
1.导入pom依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>7.1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
2.配置类
-
MinIOConfigProperties
@Data @ConfigurationProperties(prefix = "minio") // 文件上传 配置前缀file.oss public class MinIOConfigProperties implements Serializable { private String accessKey; private String secretKey; private String bucket; private String endpoint; private String readPath; }
-
MinIOConfigProperties
@Data @Configuration @EnableConfigurationProperties({MinIOConfigProperties.class}) //当引入FileStorageService接口时 @ConditionalOnClass(FileStorageService.class) public class MinIOConfig { @Autowired private MinIOConfigProperties minIOConfigProperties; @Bean public MinioClient buildMinioClient(){ return MinioClient .builder() .credentials(minIOConfigProperties.getAccessKey(), minIOConfigProperties.getSecretKey()) .endpoint(minIOConfigProperties.getEndpoint()) .build(); } }
3.封装操作minIO类
-
FileStorageService
public interface FileStorageService { /** * 上传图片文件 * @param prefix 文件前缀 * @param filename 文件名 * @param inputStream 文件流 * @return 文件全路径 */ public String uploadImgFile(String prefix, String filename,InputStream inputStream); /** * 上传html文件 * @param prefix 文件前缀 * @param filename 文件名 * @param inputStream 文件流 * @return 文件全路径 */ public String uploadHtmlFile(String prefix, String filename,InputStream inputStream); /** * 删除文件 * @param pathUrl 文件全路径 */ public void delete(String pathUrl); /** * 下载文件 * @param pathUrl 文件全路径 * @return * */ public byte[] downLoadFile(String pathUrl); }
-
MinIOFileStorageService
@Slf4j @EnableConfigurationProperties(MinIOConfigProperties.class) @Import(MinIOConfig.class) public class MinIOFileStorageService implements FileStorageService { @Autowired private MinioClient minioClient; @Autowired private MinIOConfigProperties minIOConfigProperties; private final static String separator = "/"; /** * @param dirPath * @param filename yyyy/mm/dd/file.jpg * @return */ public String builderFilePath(String dirPath,String filename) { StringBuilder stringBuilder = new StringBuilder(50); if(!StringUtils.isEmpty(dirPath)){ stringBuilder.append(dirPath).append(separator); } SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); String todayStr = sdf.format(new Date()); stringBuilder.append(todayStr).append(separator); stringBuilder.append(filename); return stringBuilder.toString(); } /** * 上传图片文件 * @param prefix 文件前缀 * @param filename 文件名 * @param inputStream 文件流 * @return 文件全路径 */ @Override public String uploadImgFile(String prefix, String filename,InputStream inputStream) { String filePath = builderFilePath(prefix, filename); try { PutObjectArgs putObjectArgs = PutObjectArgs.builder() .object(filePath) .contentType("image/jpg") .bucket(minIOConfigProperties.getBucket()).stream(inputStream,inputStream.available(),-1) .build(); minioClient.putObject(putObjectArgs); StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath()); urlPath.append(separator+minIOConfigProperties.getBucket()); urlPath.append(separator); urlPath.append(filePath); return urlPath.toString(); }catch (Exception ex){ log.error("minio put file error.",ex); throw new RuntimeException("上传文件失败"); } } /** * 上传html文件 * @param prefix 文件前缀 * @param filename 文件名 * @param inputStream 文件流 * @return 文件全路径 */ @Override public String uploadHtmlFile(String prefix, String filename,InputStream inputStream) { String filePath = builderFilePath(prefix, filename); try { PutObjectArgs putObjectArgs = PutObjectArgs.builder() .object(filePath) .contentType("text/html") .bucket(minIOConfigProperties.getBucket()).stream(inputStream,inputStream.available(),-1) .build(); minioClient.putObject(putObjectArgs); StringBuilder urlPath = new StringBuilder(minIOConfigProperties.getReadPath()); urlPath.append(separator+minIOConfigProperties.getBucket()); urlPath.append(separator); urlPath.append(filePath); return urlPath.toString(); }catch (Exception ex){ log.error("minio put file error.",ex); ex.printStackTrace(); throw new RuntimeException("上传文件失败"); } } /** * 删除文件 * @param pathUrl 文件全路径 */ @Override public void delete(String pathUrl) { String key = pathUrl.replace(minIOConfigProperties.getEndpoint()+"/",""); int index = key.indexOf(separator); String bucket = key.substring(0,index); String filePath = key.substring(index+1); // 删除Objects RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder().bucket(bucket).object(filePath).build(); try { minioClient.removeObject(removeObjectArgs); } catch (Exception e) { log.error("minio remove file error. pathUrl:{}",pathUrl); e.printStackTrace(); } } /** * 下载文件 * @param pathUrl 文件全路径 * @return 文件流 * */ @Override public byte[] downLoadFile(String pathUrl) { String key = pathUrl.replace(minIOConfigProperties.getEndpoint()+"/",""); int index = key.indexOf(separator); String bucket = key.substring(0,index); String filePath = key.substring(index+1); InputStream inputStream = null; try { inputStream = minioClient.getObject(GetObjectArgs.builder().bucket(minIOConfigProperties.getBucket()).object(filePath).build()); } catch (Exception e) { log.error("minio down file error. pathUrl:{}",pathUrl); e.printStackTrace(); } ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buff = new byte[100]; int rc = 0; while (true) { try { if (!((rc = inputStream.read(buff, 0, 100)) > 0)) break; } catch (IOException e) { e.printStackTrace(); } byteArrayOutputStream.write(buff, 0, rc); } return byteArrayOutputStream.toByteArray(); } }
4.对外加入自动配置
在resources中新建META-INF/spring.factories
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
MinIOFileStorageService路径
使用方法
1.添加minio所需要的配置
spring:
# 配置文件上传大小限制(minio文件上传)
servlet:
multipart:
max-file-size: 200MB
max-request-size: 200MB
minio:
accessKey: minio
secretKey: minio123
bucket: 文件在minio中的主目录命名
endpoint: http://主机IP:9000
readPath: http://主机IP:9000
2.在对应使用的业务类中注入FileStorageService
例:
@SpringBootTest(classes = MinioApplication.class)
@RunWith(SpringRunner.class)
public class MinioTest {
@Autowired
private FileStorageService fileStorageService;
@Test
public void testUpdateImgFile() {
try {
FileInputStream fileInputStream = new FileInputStream("E:\\tmp\\ak47.jpg");
String filePath = fileStorageService.uploadImgFile("", "ak47.jpg", fileInputStream);
System.out.println(filePath);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
#安装(使用DOCKER)
-
拉取镜像
docker pull minio/minio
-
部署容器
docker run -p 9000:9000 --name minio -d --restart=always -e "MINIO_ACCESS_KEY=minio" -e "MINIO_SECRET_KEY=minio123" -v /home/data:/data -v /home/config:/root/.minio minio/minio server /data