SpringBoot项目集成MinIO
一、MinIO的下载安装以及基本使用
1.下载地址:https://dl.min.io/server/minio/release/windows-amd64/minio.exe
2.下载好后需要手动创建data文件夹用于存储MinIO中的数据
3.键入cmd

4. 设置MinIO的一些变量(第一次启动需要配置)
set MINIO_ROOT_USER=admin set MINIO_ROOT_PASSWORD=admin123 set MINIO_ACCESS_KEY=admin set MINIO_SECRET_KEY=admin123
5.下面是我踩的坑,如果只设置了MINIO_ROOT_USER和MINIO_ROOT_PASSWORD的值,而不设置MINIO_ACCESS_KEY和MINIO_SECRET_KEY的值,当启动minio服务的时候就会报以下异常:

所以一定要设置好后面两个变量的值。
6. 启动minio服务
minio.exe server data

7.进入登录页面后,输入对应的用户名和密码,也就是之前设置的MINIO_ROOT_USER和MINIO_ROOT_PASSWORD的值。

8. 进入主界面后,点击左侧导航栏中的Buckets,然后点击Create Bucket。

9.进入该桶,点击upload,上传一个文件,桶的默认权限是private,所以外界访问不到,需要修改访问权限为public,但是要注意安全问

点击左侧导航栏中的Buckets,进入该桶,修改权限为public,这样外界就可以访问上传的文件了。

二. SpringBoot集成MinIO
1.引入依赖
<dependency>
<groupId>io.minio</groupId>
<artifactId>minio</artifactId>
<version>7.0.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
2.编写配置文件
server:
port: 8080
spring:
# 配置文件上传大小限制
servlet:
multipart:
max-file-size: 200MB
max-request-size: 200MB
minio:
host: http://127.0.0.1:9000 # 访问地址
url: ${minio.host}/${minio.bucket}/ # 对象存储服务的url
access-key: minioadmin # 登录账号
secret-key: minioadmin # 登录账号密码
bucketName: test-bucket # 文件桶的名称
bucket: public // 权限
3.编写minio配置类
@Configuration
public class MinIoClientConfig {
/**
* minio配置
*/
@Value("${minio.url}")
private String endpoint;
@Value("${minio.accessKey}")
private String accessKey;
@Value("${minio.secretKey}")
private String secretKey;
@Value("${minio.bucketName}")
private String bucketName; /**
* 注入minio客户端
*
* @return minio客户端对象
*/
@Bean
public MinioClient minioClient() {
return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();
}
}
4.编写minio工具类
@Component
public class MinioUtil { /**
* minio配置
*/
@Value("${minio.url}")
private String endpoint; @Autowired
private MinioClient minioClient; /**
* 创建一个桶
*/
public void createBucket(String bucket) throws Exception {
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
if (!found) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
}
} /**
* 上传一个文件
*/
public void uploadFile(InputStream stream, String bucket, String objectName) throws Exception {
ObjectWriteResponse objectWriteResponse = minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName)
.stream(stream, -1, 10485760).build()); System.out.println(objectWriteResponse.object() + " is uploaded successfully.");
} /**
* 列出所有的桶
*/
public List<String> listBuckets() throws Exception {
List<Bucket> list = minioClient.listBuckets();
List<String> names = new ArrayList<>();
list.forEach(b -> {
names.add(b.name());
});
return names;
} /**
* 列出一个桶中的所有文件和目录
*/
public List<Fileinfo> listFiles(String bucket) throws Exception {
Iterable<Result<Item>> results = minioClient.listObjects(
ListObjectsArgs.builder().bucket(bucket).recursive(true).build()); List<Fileinfo> infos = new ArrayList<>();
results.forEach(r->{
Fileinfo info = new Fileinfo();
try {
Item item = r.get();
info.setFilename(item.objectName());
info.setDirectory(item.isDir());
info.setFilepath(endpoint+"/"+bucket+"/"+item.objectName());
infos.add(info);
} catch (Exception e) {
e.printStackTrace();
}
});
return infos;
} /**
* 下载一个文件
*/
public InputStream download(String bucket, String objectName) throws Exception {
InputStream stream = minioClient.getObject(
GetObjectArgs.builder().bucket(bucket).object(objectName).build());
return stream;
} /**
* 删除一个桶
*/
public void deleteBucket(String bucket) throws Exception {
minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
} /**
* 删除一个对象
*/
public void deleteObject(String bucket, String objectName) throws Exception {
minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectName).build());
} /**
* 复制文件
*/
public void copyObject(String sourceBucket, String sourceObject, String targetBucket, String targetObject) throws Exception {
this.createBucket(targetBucket);
minioClient.copyObject(CopyObjectArgs.builder().bucket(targetBucket).object(targetObject)
.source(CopySource.builder().bucket(sourceBucket).object(sourceObject).build()).build());
} /**
* 获取文件信息
*/
public String getObjectInfo(String bucket, String objectName) throws Exception {
return minioClient.statObject(StatObjectArgs.builder().bucket(bucket).object(objectName).build()).toString(); } /**
* 生成一个给HTTP GET请求用的presigned URL。
* 浏览器/移动端的客户端可以用这个URL进行下载,
* 即使其所在的存储桶是私有的。
*/
public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) throws Exception {
GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs
.builder().bucket(bucketName).object(objectName).expiry(expires).method(Method.GET).build();
return minioClient.getPresignedObjectUrl(build);
} /**
* 获取minio中所有的文件
*/
public List<Fileinfo> listAllFile() throws Exception {
List<String> list = this.listBuckets();
List<Fileinfo> fileinfos = new ArrayList<>();
for (String bucketName : list) {
fileinfos.addAll(this.listFiles(bucketName));
}
return fileinfos;
}
}
5.编写文件实体类
@Data
public class Fileinfo {
String filename;
String filepath;
Boolean directory;
}
6.编写接口响应实体
@Data
public class ResultData<T> { public static final Integer SUCCESS_CODE = 200;
public static final Integer FAIL_CODE = 4000;
public static final String SUCCESS_MESSAGE = "操作成功";
public static final String FAIL_MESSAGE = "操作失败";
/**
* 返回状态码
*/
private Integer code;
/**
* 返回信息
*/
private String message; /**
* 返回数据
*/
private T data; public ResultData() { } public static <T> ResultData<T> success() {
ResultData<T> resultUtil = new ResultData<>();
resultUtil.setCode(SUCCESS_CODE);
resultUtil.setMessage(SUCCESS_MESSAGE);
return resultUtil;
} public static <T> ResultData<T> success(T data) {
ResultData<T> resultUtil = success();
resultUtil.setData(data);
return resultUtil;
} public static <T> ResultData<T> success(String message, T data) {
ResultData<T> resultUtil = success();
resultUtil.setMessage(message);
resultUtil.setData(data);
return resultUtil;
} public static <T> ResultData<T> success(Integer code, String message, T data) {
ResultData<T> resultUtil = new ResultData<>();
resultUtil.setCode(code);
resultUtil.setMessage(message);
resultUtil.setData(data);
return resultUtil;
} public static <T> ResultData<T> success(Integer code, String message,Integer count, T data) {
ResultData<T> resultUtil = new ResultData<>();
resultUtil.setCode(code);
resultUtil.setMessage(message);
resultUtil.setData(data);
return resultUtil;
} public static <T> ResultData<T> fail() {
ResultData<T> resultUtil = new ResultData<>();
resultUtil.setCode(FAIL_CODE);
resultUtil.setMessage(FAIL_MESSAGE);
return resultUtil;
} public static <T> ResultData<T> fail(T data) {
ResultData<T> resultUtil = fail();
resultUtil.setData(data);
return resultUtil;
} public static <T> ResultData<T> fail(String message, T data) {
ResultData<T> resultUtil = fail();
resultUtil.setMessage(message);
resultUtil.setData(data);
return resultUtil;
} public static <T> ResultData<T> fail(Integer code, String message) {
ResultData<T> resultUtil = fail();
resultUtil.setCode(code);
resultUtil.setMessage(message);
return resultUtil;
} public static <T> ResultData<T> fail(Integer code, String message, T data) {
ResultData<T> resultUtil = new ResultData<>();
resultUtil.setCode(code);
resultUtil.setMessage(message);
resultUtil.setData(data);
return resultUtil;
} public void setCode(int code){
this.code = code;
}
public int getCode(){
return this.code;
}
public void setMessage(String message){
this.message = message;
}
public String getMessage(){
return message;
}
public void setData(T data){
this.data = data;
}
public T getData(){
return data;
}
}
7.创建minio控制器
/**
* minio相关接口
*
* @author songwp
* @date 2024/11/11 11:28
*/
@RestController
@RequestMapping("minio")
public class MinioController { @Autowired
MinioUtil minioUtil; /**
* 文件上传
*
* @param file 文件
* @param bucket 桶名
* @param objectName 对象名
* @return 是否成功
* @throws Exception
*/
@RequestMapping(value = "/upload", method = RequestMethod.POST)
public ResultData upload(@RequestParam MultipartFile file,
@RequestParam String bucket,
@RequestParam(required = false) String objectName) throws Exception {
minioUtil.createBucket(bucket);
if (objectName != null) {
minioUtil.uploadFile(file.getInputStream(), bucket, objectName + "/" + file.getOriginalFilename());
} else {
minioUtil.uploadFile(file.getInputStream(), bucket, file.getOriginalFilename());
}
return ResultData.success();
} /**
* 获取文件信息
* @param bucket 桶名
* @return 是否成功
*/
@RequestMapping(value = "/getFile", method = RequestMethod.GET)
public ResultData getFile(@RequestParam ("bucket")String bucket){
try {
List<Fileinfo> fileinfos = minioUtil.listFiles(bucket);
return ResultData.success(fileinfos);
} catch (Exception e) {
throw new RuntimeException(e);
}
} /**
* 文件下载
*
* @param bucket 桶名
* @param objectName 对象名
* @return 是否成功
*/
@GetMapping("download")
public ResultData download(@RequestParam("bucket") String bucket,
@RequestParam("objectName") String objectName){
try {
InputStream download = minioUtil.download(bucket, objectName);
return ResultData.success();
} catch (Exception e) {
throw new RuntimeException(e);
}
} /**
* 获取文件信息
*
* @param bucket 桶名
* @param objectName 对象名
* @return 是否成功
*/
@GetMapping("getObjectInfo")
public ResultData getObjectInfo(@RequestParam("bucket") String bucket,
@RequestParam("objectName") String objectName) throws Exception {
String objectInfo = minioUtil.getObjectInfo(bucket, objectName);
String objectStat = objectInfo.replaceAll("ObjectStat", "");
return ResultData.success(objectStat);
} /**
* 生成一个给HTTP GET请求用的presigned URL。
*
* @param bucket 桶名
* @param objectName 对象名
* @return 是否成功
*/
@GetMapping("getObjectUrl")
public ResultData getObjectUrl(@RequestParam("bucket") String bucket,
@RequestParam("objectName") String objectName) throws Exception {
String url = minioUtil.getPresignedObjectUrl(bucket, objectName,7200);
return ResultData.success(url);
} /**
* 列出所有的桶
*/
@RequestMapping(value = "/listBuckets", method = RequestMethod.GET)
public ResultData listBuckets() throws Exception {
return ResultData.success(minioUtil.listBuckets());
} /**
* 获取minio中所有的文件
*/
@RequestMapping(value = "/listAllFile", method = RequestMethod.GET)
public ResultData listAllFile() throws Exception {
return ResultData.success(minioUtil.listAllFile());
}
}
8.postman接口调用实例

9.最后查看test-bucket桶中是否有刚才上传的文件就可以了。如果有则表明你的项目已经成功集成minio了

SpringBoot项目集成MinIO的更多相关文章
- SpringBoot项目集成Hystrix
Hystrix Hystrix是由Netflix开源的一个服务隔离组件,通过服务隔离来避免由于依赖延迟.异常,引起资源耗尽导致系统不可用的解决方案. 1.什么是服务熔断 服务熔断就是对该服务的调用 ...
- SpringBoot项目集成PageHelper使用
SpringBoot项目集成PageHelper使用 一.开始 地址:https://github.com/pagehelper/Mybatis-PageHelper 在spring boot ...
- 七、SpringBoot项目集成JSP以及项目不同启动方式及访问路径配置
1.创建JSP目录 在src/main目录下创建目录webapp/WEB-INF/jsp用于存放jsp页面,如下图: 然后再改文件夹下面我们创建JSP文件: 大家在使用IDEA 的new菜单创建JSP ...
- springboot项目集成activity
1.按照上一篇博客,新建好springboot项目后,在项目pom.xml文件中添加activity依赖 <dependency> <groupId>org.activiti& ...
- Springboot项目集成JPush极光推送(Java SDK)
1.由于项目的需求,需要在Android APP上实现消息推送功能,所以引用了极光推送(官网:https://www.jiguang.cn/, 文档:http://docs.jiguang.cn/) ...
- 使用IDEA快速搭建基于Maven的SpringBoot项目(集成使用Redis)
迫于好久没写博客心慌慌,随便写个简单版的笔记便于查阅. 新建项目 新建项目 然后起名 继续next netx finish. 首先附上demo的项目结构图 配置pom.xml <?xml ver ...
- ElasticSearch(九):springboot项目集成消息中间件activeMQ
目的:为了将elasticsearch做成单独的服务,那么我们必须解耦,也就是业务逻辑和搜索模块是没有关系的,并且是异步的.那么项目之间通信,使用的选择有限,消息中间件是一个不错的选择. 消息中间件常 ...
- SpringBoot项目集成socketIo实现实时推送
netty-socketio maven依赖 <dependency> <groupId>com.corundumstudio.socketio</groupId> ...
- SpringBoot项目集成cas单点登录
添加依赖 添加cas client依赖 <dependency> <groupId>net.unicon.cas</groupId> <artifactId& ...
- SpringBoot项目集成Redis
一.在pom文件中添加依赖 <!-- 集成redis --> <dependency> <groupId>org.springframework.boot</ ...
随机推荐
- element-UI tree树形控件 修改小三角图标
.el-tree /deep/ .el-tree-node__expand-icon.expanded{ -webkit-transform: rotate(0deg); transform: rot ...
- SMU Autumn 2023 Round 2(Div.1+2)
SMU Autumn 2023 Round 2(Div.1+2) C. Chaotic Construction 把环展开的话就是\(1 \sim 2n\),若\(D\)的位置放上路障的话,在这个展开 ...
- Linux下简单几步安装AI开发环境-ROS(超有意思)
机缘巧合,接触到了一个开源的项目ROS,只需要根据一口君的操作,就可以很容易搭建一个具有3d效果的开发环境,非常有意思,和大家分享下. 0.什么是ROS ROS(Robot Operating Sys ...
- 9个Linux 查看系统硬件信息命令(实例详解)
在Linux下,我们精要遇到需要查看系统的硬件信息, 这里我罗列了查看系统硬件信息的实用命令,并做了分类,实例解说. 执行环境:ubuntu 16.04 1. cpu lscpu命令,查看的是cpu的 ...
- JavaScript设计模式样例八 —— 适配器模式
适配器模式(Adapter Pattern) 定义:将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能一起工作的那些类能一起工作.目的:主要解决在软件系统中,常常要将一些&quo ...
- 低版本安卓home assistant网页浏览器
试了很久 一直有问题的一点 , 使用普通浏览器加载不出来登录界面 只能加载出icon 然后就没反应了 考虑到了webview的问题 但是没想到安卓5.0之前是固定且不可升级的webview 从 And ...
- Ansible 知识
Ref: guru99.com/ansible-tutorial.html https://www.digitalocean.com/community/tutorials/how-to-use-an ...
- Round #2022/11/26
问题 B:染色 题目描述 有长度为 \(n\) 的一个序列,编号为 \(1\) 到 \(n\) ,现要对这些元素进行染色标记,若编号 \(i-j\) 为素数,且 \(1\le i < j \le ...
- 开发一个属性名提示友好的Vue组件
这两天开发了一个组件,开发好之后想着先本地npm link 用一用试试,然后在vue3 项目中link了过来,发现VSCODE没有属性提示,鉴于考虑到一个好的组件应该是提示友好的,于是给组件准备加上属 ...
- 小tips:怎样实现简单的前端hash与history路由方式?
前端路由实现方式,主要有两种,分别是history和hash模式. hash模式 不同路由对应的hash是不一样的,如何能够监听到URL中关于hash部分发生的变化?浏览器已经暴露给我们一个现成的方法 ...