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</ ...
随机推荐
- WM_ERASEBKGND
WM_ERASEBKGND是在当窗口背景必须被擦除时 (例如,窗口的移动,窗口的大小的改变)才发送. 当窗口的一部分无效需要重绘时发送此消息. #define WM_ERASEBKGND 0x0014 ...
- Dialog封装的消息映射(弄了好久终于弄过了,不是静态函数哦,和MFC一样,嘻嘻)
前面弄的是全局的仿消息映射,现在这是封装到类中的消息映射,一直弄不明白,现在也不太明白,就是今天在看虚函数表的用法视频时有位老师用了个共有体转化全局函数为类成员函数,这就给我指了条明路,这不今晚又来弄 ...
- 折腾 Quickwit,Rust 编写的分布式搜索引擎 - 从不同的来源摄取数据
摄取 API 在这节教程中,我们将介绍如何使用 Ingest API 向 Quickwit 发送数据. 要跟随这节教程,您需要有一个本地的 Quickwit 实例正在运行. https://quick ...
- 【测试平台开发】——01后端web开发框架Flask
官方中文地址:https://flask.net.cn/ 官方英文地址:https://flask.palletsprojects.com/en/2.1.x/ github地址:https://git ...
- elastersearch7.6.1搭建及基本操作详解
搭建 修改系统参数 vim /etc/security/limits.conf * soft nofile 655350 * hard nofile 655350 * soft nofile 6553 ...
- 怎么在Windows操作系统部署阿里开源版通义千问(Qwen2)
怎么在Windows操作系统部署阿里开源版通义千问(Qwen2) | 原创作者/编辑:凯哥Java | 分类:人工智能学习系列教程 GitHu ...
- Maven的下载安装配置
Maven的下载安装配置 Maven是什么 Maven是基于项目对象模型(POM project object model),可以通过一小段描述信息(配置)来管理项目的构建,报告和文档的软件项目管理工 ...
- Git使用经验总结6-删除远端历史记录
删除远端的历史记录但是不影响最新的仓库内容是笔者一直想实现的功能,有两个很不错的用处: 有的历史提交不慎包含了比较敏感的信息,提交的时候没注意,过了一段时间才发现.这个时候已经有了很多新的历史提交,无 ...
- 704 二分查找 golang实现
二分查找(Binary Search)是一种高效的查找算法,适用于 有序数组 或 有序列表.它的基本思想是通过将搜索范围逐渐缩小到目标元素所在的一半,从而大大减少查找的次数. 二分查找的基本原理 排序 ...
- Canvas简历编辑器-Monorepo+Rspack工程实践
Canvas简历编辑器-Monorepo+Rspack工程实践 在之前我们围绕Canvas聊了很多代码设计层面的东西,在这里我们聊一下工程实践.在之前的文中我也提到过,因为是本着学习的态度以及对技术的 ...