SpringBoot整合MinIO
1.MinIO简介
就是一个文件服务,官网上说是世界上最快的对象存储。其开源协议是AGPLv3。也就是说,商用要收费,个人若将MinIO用在开源项目上是不收费的。
2.MinIO部署
MinIO有多种部署方式,我最喜欢的还是docker部署,简单又方便。
docker pull minio/minio
docker run -d -p 9000:9000 -p 9091:9091 --name=minio --restart=always -e "MINIO_ACCESS_KEY=admin" -e "MINIO_SECRET_KEY=admin123" -v /Users/yangnanfeng/Documents/temp/upload/data:/data -v /Users/yangnanfeng/Documents/temp/upload/data:/root/.minio minio/minio server /data --console-address ":9091" --address ":9000"
两个 -v 要映射到咱们本地文件上,当然,你甚至可以不写。
两个 -e 对应用户名【admin】和密码 【admin123】
安装完毕后我们来验证一下。
①登录MinIO管理网页。账号 admin 密码 admin123
localhost:9000
②熟悉一下界面
③新建一个桶
③我们上传一个图片试试,并访问这张图片。
3.代码实现
如上可以手动上传下载,那么如何用Java代码进行上传下载删除呢,我们采用SpringBoot。
3.1创建一个Maven项目
<?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>
<artifactId>spring-boot-parent</artifactId>
<groupId>org.springframework.boot</groupId>
<version>2.3.1.RELEASE</version>
</parent>
<groupId>org.example</groupId>
<artifactId>SpringBoot-MinIO</artifactId>
<dependencies>
<!--web-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--minio-->
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>8.4.3</version>
</dependency>
</dependencies>
</project>
3.2 SpringBoot启动类搞起来
package com.nanfeng.minio;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class);
}
}
基础工作弄完了。
3.3创建application.properties
其实我个人更喜欢properties,因为yml有时候复制来复制去,空格就搞掉了,格式乱了有点麻烦。
## minio 的UTL
minio.endpoint=http://localhost:9000
## minio 的账号密码
minio.accessKey=admin
minio.secretKey=admin123
## minio 的自己建的桶
minio.bucket.test=test
3.4创建MinIO的配置类 并放在config包下面
package com.nanfeng.minio.config;
import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MinioConfig {
//读取参数
@Value("${minio.endpoint}")
private String endpoint;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
@Bean
public MinioClient minioClient() {
MinioClient minioClient =
MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
return minioClient;
}
}
实际上minioClient自带的API很丰富,到这一步就ok了。下面是锦上添花的功能。
3.5弄一个操作类,相当于一个工具包
创建一个service包
package com.nanfeng.minio.service;
import io.minio.*;
import io.minio.errors.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
/**
* minio 操作类
*/
@Service
public class MinIOService {
// 我最喜欢用@Resource 强烈建议不要用@autowire
@Resource
private MinioClient minioClient;
@Value("${minio.bucket.test}")
private String bucket;
@Value("${minio.endpoint}")
private String endpoint;
/**
* 本地文件上传
* @param localPath 本地路径
* @param remotePath 远程路径
* @return 可访问地址
*/
public String upload(String localPath,String remotePath) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
UploadObjectArgs uploadObjectArgs = UploadObjectArgs.builder()
.bucket(bucket)
.object(localPath)
.filename(remotePath)
.build();
minioClient.uploadObject(uploadObjectArgs);
return endpoint + "/" + bucket + "/" + remotePath;
}
/**
* 用流上传
* @param is 文件流
* @param remotePath 远程路径
* @return 可访问地址
*/
public String upload(InputStream is, String remotePath) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
PutObjectArgs args = PutObjectArgs.builder()
.bucket(bucket)
.object(remotePath)
.stream(is, -1, 10485760)
.build();
minioClient.putObject(args);
return endpoint + "/" + bucket + "/" + remotePath;
}
/**
* 删除文件
* @param remotePath 远程路径
* @return
*/
public void delete(String remotePath) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
RemoveObjectArgs args = RemoveObjectArgs.builder()
.bucket(bucket)
.object(remotePath)
.build();
minioClient.removeObject(args);
}
/**
* 获取流
* @param remotePath 远程路径
*/
public InputStream getInputStream(String remotePath) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
GetObjectArgs args = GetObjectArgs.builder()
.bucket(bucket)
.object(remotePath)
.build();
return minioClient.getObject(args);
}
}
3.6 写一个controller用来测试一下。
package com.nanfeng.minio.controller;
import com.nanfeng.minio.service.MinIOService;
import io.minio.errors.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
@RestController
public class MinIOController {
@Resource
private MinIOService minIOService;
@PostMapping("/upload")
public HashMap<String, String> upload(@RequestParam(name = "file", required = false) MultipartFile file) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
String originalFilename = file.getOriginalFilename();
assert originalFilename != null;
String fileName = System.currentTimeMillis() + originalFilename.substring(originalFilename.lastIndexOf("."));
String url = minIOService.upload(file.getInputStream(), fileName);
HashMap<String, String> map = new HashMap<String, String>();
map.put("url",url);
map.put("fileName",fileName);
return map;
}
@GetMapping("/remove")
public String remove(String fileName) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
minIOService.delete(fileName);
return "success";
}
}
4.代码写完了,postman测试一下。
①上传功能
返回参数fileName 为对象名、url则可直接访问。
文件上传成功
②删除功能
入参为对象名,出参success表示成功。
5.整个项目的git如下,开箱即用。