springboot 对接 minio 分布式文件系统

1. minio介绍

Minio 是一个基于Go语言的对象存储服务。它实现了大部分亚马逊S3云存储服务接口,可以看做是是S3的开源版本,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5T不等。区别于分布式存储系统,minio的特色在于简单、轻量级,对开发者友好,认为存储应该是一个开发问题而不是一个运维问题。


2. minio下载地址

下载

3. liunx minio文件授权

chomd +x minio

4. 编写启动minio shell文件

vi run.sh

#!/bin/bash
#web管理界面登录用户
export MINIO_ROOT_USER=minio
#web管理界面登录密码
export MINIO_ROOT_PASSWORD=minio
#生成共享链接时,需要配置,否则是本地地址127.0.0.1,有地址的可以修改为自己地址
export MINIO_SERVER_URL=http://IP:9002
# nohup启动服务 指定文件存放路径 /root/data 还有设置日志文件路径 /root/minio/log
nohup ./minio server --address :9002 --console-address :9001 /root/data/minio > /root/logs/minio.log 2>&1 &

5. 赋权限给予shell文件run.sh文件

 chmod u+x run.sh

.

6. 启动minio服务,执行sh文件

bash run.sh

7. 查看日志,我们在4的时候最后一条上有配置log地址

tail -f /root/logs/minio.log

8. 浏览器访问minio界面,并且输入在第四步配置的账号密码

9. 接下来我们可以创建一个我们作为测试的文件桶

 

 10. 当我们创建好桶之后,我们可以前往查看是否存在

11. 点击桶进入,手动测试上传文件

12. 上传文件之后我们可以选择某一个文件进行下载或者链接共享,链接共享默认时间为7天

13. 当我们点击共享时,会出现一个共享链接,我们可以直接在浏览器内查看相对应的文件

14. springboot 对接minio,加入POM文件

  <dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>7.1.0</version></dependency>

15. 配置application文件

生成请求账号密码

minio:endpoint: http://IP:9002accessKey: bjdZxvMDxAzYETgYn0aY 配置账号secretKey: uk7srkLHsYkwzvTYVzDBtwzlXz5fxsoMmNpbb3SN 配置密码bucketName: test 桶名称-默认

16.springboot 工具类

package com.project.google.util;/*** @Description: TODO* @Author xgp* @Date 2023/8/7 8:05* @PackageName:com.project.google.util* @ClassName: MinioTemplate* @Version 1.0*/import io.minio.*;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.SneakyThrows;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;/*** Minio 基础操作类** @author: zhanghuaiyu* @since 2021-01-22 16:27*/
@Configuration
public class MinioTemplate implements InitializingBean {private MinioClient minioClient;@Value("${minio.endpoint}")private String url;@Value("${minio.accessKey}")private String accessKey;@Value("${minio.secretKey}")private String secretKey;@Overridepublic void afterPropertiesSet() {Assert.hasText(url, "Minio url 为空");Assert.hasText(accessKey, "Minio accessKey为空");Assert.hasText(secretKey, "Minio secretKey为空");this.minioClient = new MinioClient(url, accessKey, secretKey);}/*** 创建bucket* setBucketPolicy 设置权限才可以预览** @param bucketName bucket名称*/@SneakyThrowspublic Boolean createBucket(String bucketName) {if (!bucketExists(bucketName)) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());StringBuilder builder = new StringBuilder();builder.append("{\n");builder.append("    \"Statement\": [\n");builder.append("        {\n");builder.append("            \"Action\": [\n");builder.append("                \"s3:GetBucketLocation\",\n");builder.append("                \"s3:ListBucket\"\n");builder.append("            ],\n");builder.append("            \"Effect\": \"Allow\",\n");builder.append("            \"Principal\": \"*\",\n");builder.append("            \"Resource\": \"arn:aws:s3:::bucketname\"\n");builder.append("        },\n");builder.append("        {\n");builder.append("            \"Action\": \"s3:GetObject\",\n");builder.append("            \"Effect\": \"Allow\",\n");builder.append("            \"Principal\": \"*\",\n");builder.append("            \"Resource\": \"arn:aws:s3:::my-bucketname/*.*\"\n");builder.append("        }\n");builder.append("    ],\n");builder.append("    \"Version\": \"2012-10-17\"\n");builder.append("}\n");minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(builder.toString().replace("bucketname", bucketName)).build());return true;} else {return false;}}/*** 获取全部bucket* <p>* https://docs.minio.io/cn/java-client-api-reference.html#listBuckets*/@SneakyThrowspublic List<Bucket> getAllBuckets() {return minioClient.listBuckets();}/*** 根据bucketName获取信息** @param bucketName bucket名称*/@SneakyThrowspublic Optional<Bucket> getBucket(String bucketName) {return minioClient.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();}/*** 根据bucketName删除信息** @param bucketName bucket名称*/@SneakyThrowspublic void removeBucket(String bucketName) {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());}/*** 根据文件前置查询文件** @param bucketName bucket名称* @param prefix     前缀* @param recursive  是否递归查询* @return MinioItem 列表*/@SneakyThrowspublic List getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) {List<Item> list = new ArrayList<>();Iterable<Result<Item>> objectsIterator = minioClient.listObjects(bucketName, prefix, recursive);if (objectsIterator != null) {Iterator<Result<Item>> iterator = objectsIterator.iterator();if (iterator != null) {while (iterator.hasNext()) {Result<Item> result = iterator.next();Item item = result.get();list.add(item);}}}return list;}/*** 获取文件外链** @param bucketName bucket名称* @param objectName 文件名称* @param expires    过期时间 <=7* @return url*/@SneakyThrowspublic String getObjectUrl(String bucketName, String objectName, Integer expires) {return minioClient.presignedGetObject(bucketName, objectName, expires);}/*** 获取文件路径** @param bucketName* @param fileName* @return*/@SneakyThrowspublic String getObjectUrl(String bucketName, String fileName) {return minioClient.getObjectUrl(bucketName, fileName);}/*** 获取文件** @param bucketName bucket名称* @param objectName 文件名称* @return 二进制流*/@SneakyThrowspublic InputStream getObject(String bucketName, String objectName) {return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());}/*** 获取文件** @param bucketName* @param objectName* @return*/@SneakyThrowspublic ObjectStat statObject(String bucketName, String objectName) {return minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());}/*** 上传文件** @param bucketName bucket名称* @param objectName 文件名称* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject*/public String putObject(String bucketName, String objectName, MultipartFile file) throws Exception {if (!this.bucketExists(bucketName)) {this.createBucket(bucketName);}minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(file.getInputStream(), file.getSize(), PutObjectArgs.MIN_MULTIPART_SIZE).contentType(file.getContentType()).build());return bucketName;}/*** 上传文件** @param bucketName bucket名称* @param objectName 文件名称* @param stream     文件流* @param size       大小* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject*/public void putObject(String bucketName, String objectName, InputStream stream, long size) throws Exception {minioClient.putObject(bucketName, objectName, stream, new PutObjectOptions(stream.available(), -1));}/*** 获取文件信息, 如果抛出异常则说明文件不存在** @param bucketName bucket名称* @param objectName 文件名称* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject*/public ObjectStat getObjectInfo(String bucketName, String objectName) throws Exception {return minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());}/*** 删除文件** @param bucketName bucket名称* @param objectName 文件名称* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#removeObject*/public void removeObject(String bucketName, String objectName) throws Exception {minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());}/*** 批量删除文件夹内所有文件** @param bucketName bucket名称* @param objectName 文件名称* @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#removeObject*/public void removeObjects(String bucketName, String objectName) throws Exception {List<Item> list = getAllObjectsByPrefix(bucketName, objectName, false);for (Item item : list) {removeObject(bucketName, item.objectName());}}@SneakyThrowspublic boolean bucketExists(String bucketName) {return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());}/*** 文件下载** @param response* @param bucket* @param objectName* @param outName* @throws Exception*/public void download(HttpServletResponse response, String bucket, String objectName, String outName) throws Exception {ObjectStat stat = this.statObject(bucket, objectName);response.setContentType(stat.contentType());response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(outName, "UTF-8"));response.setHeader("FileName", URLEncoder.encode(outName, "UTF-8"));InputStream in = this.getObject(bucket, objectName);IOUtils.copy(in, response.getOutputStream());in.close();}/*** 合并分片文件到指定目录** @param bucket* @param fileName* @param sources* @return* @throws Exception*/public ObjectWriteResponse composeObject(String bucket, String fileName, List<ComposeSource> sources) throws Exception {ObjectWriteResponse response = minioClient.composeObject(ComposeObjectArgs.builder().bucket(bucket).object(fileName).sources(sources).build());return response;}
}

 17.请求测试controller方法

package com.project.google.controller;import afu.org.checkerframework.checker.oigj.qual.O;
import com.project.google.util.MinioTemplate;
import io.minio.messages.Bucket;
import org.apache.commons.io.IOUtils;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
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 java.io.IOException;
import java.io.InputStream;
import java.util.*;/*** @Description: TODO* @Author xgp* @Date 2023/8/7 8:35* @PackageName:com.project.google.controller* @ClassName: TbMinioController* @Version 1.0*/
@RestController
public class TbMinioController {@Autowiredprivate MinioTemplate minioTemplate;//创建新的桶@GetMapping("createBucket")public Object createBucket(String bucketName){return minioTemplate.createBucket(bucketName);}//获取对应桶信息@GetMapping("getList")public Object getList(String bucketName){Bucket bucket = minioTemplate.getBucket(bucketName).get();Map<String,Object> map = new HashMap<>();map.put("name",bucket.name());map.put("createDate",bucket.creationDate());return map;}//获取所有桶信息@GetMapping("getAll")public Object getAll(){List<Map> list = new ArrayList<>();List<Bucket> buckets = minioTemplate.getAllBuckets();buckets.stream().forEach(item -> {Map<String,Object> map = new HashMap<>();map.put("name",item.name());map.put("createDate",item.creationDate());list.add(map);});return list;}/**上传文件到对应桶里,如果你想放入指定文件夹,传入文件名前面带上文件夹名称及路径,比如 test文件夹就- test/文件名,依次类推*/@PostMapping("uploadFile")public Object uploadFile(@RequestParam("file") MultipartFile file) throws Exception {/**文件夹属性,可加载文件前方*/return minioTemplate.putObject("test","uu/" + file.getOriginalFilename(),file);}/**获取图片信息,二进制数据转换为图片呈现*/@GetMapping(value = "getFile", produces = MediaType.IMAGE_JPEG_VALUE)public byte[] getFile(@RequestParam("bucketName") String bucketName,@RequestParam("objectName") String objectName) throws IOException {InputStream stream = minioTemplate.getObject(bucketName, objectName);byte[] bytes = IOUtils.toByteArray(stream);return bytes;}/**获取图片分享链接,expires为过期时间,可为小于等于7*/@GetMapping(value = "getObjectUrl")public String getObjectUrl(@RequestParam("bucketName") String bucketName,@RequestParam("objectName") String objectName) throws IOException {return minioTemplate.getObjectUrl(bucketName, objectName, 1);}}

18.接口测试

18.1 查询test bucket信息

 

18.2 获取所有bucket信息

18.3 上传文件,我这边是通过apipox进行测试

18.4 查看图片信息

18.5 生成共享链接

到此,整个对接过程就已经差不多了,其他扩展功能,如有需要,可以咨询这边,给出解答或者思路。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/79200.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

npm install时出现的问题Failed at the node-sass@4.14.1 postinstall script

从阿里云上拉取下来项目后&#xff0c;首先使用npm install 命令进行安装所需依赖&#xff0c;意想不到的事情发生了&#xff0c;报出了Failed at the node-sass4.14.1 postinstall script&#xff0c;这个问题&#xff0c;顿时一脸懵逼&#xff1b;询问前端大佬&#xff0c;给…

内存快照:宕机后,Redis如何实现快速恢复?RDB

AOF的回顾 回顾Redis 的AOF的持久化机制。 Redis 避免数据丢失的 AOF 方法。这个方法的好处&#xff0c;是每次执行只需要记录操作命令&#xff0c;需要持久化的数据量不大。一般而言&#xff0c;只要你采用的不是 always 的持久化策略&#xff0c;就不会对性能造成太大影响。 …

CS 144 Lab Six -- building an IP router

CS 144 Lab Six -- building an IP router 引言路由器的实现测试 对应课程视频: 【计算机网络】 斯坦福大学CS144课程 Lab Six 对应的PDF: Lab Checkpoint 5: building an IP router 引言 在本实验中&#xff0c;你将在现有的NetworkInterface基础上实现一个IP路由器&#xf…

scala连接mysql数据库

scala中通常是通过JDBC组件来连接Mysql。JDBC, 全称为Java DataBase Connectivity standard。 加载依赖 其中包含 JDBC driver <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.29&l…

分库分表之基于Shardingjdbc+docker+mysql主从架构实现读写分离 (三)

本篇主要说明&#xff1a; 1. 因为这个mysql版本是8.0&#xff0c;所以当其中一台mysql节点挂掉之后&#xff0c;主从同步&#xff0c;甚至双向数据同步都失效了&#xff0c;所以本篇主要记录下当其中的节点挂掉之后如何再次生效。另外推荐大家使用mysql5.7的版本&#xff0c;这…

Opencv-C++笔记 (14) : 霍夫变换(直线、圆)

文章目录 一、霍夫变换-直线1.1霍夫变换-直线 原理详解 二、霍夫圆检测 一、霍夫变换-直线 Hough Line Transform用来做直线检测 前提条件 – 边缘检测已经完成 1、平面空间&#xff08;x,y&#xff09;到极坐标空间转换&#xff1b; 2、对极坐标进行变换&#xff0c;转化为…

FL Studio Producer Edition 21 v21.0.3 Build 3517 Windows/mac官方中文版

FL Studio Producer Edition 21 v21.0.3 Build 3517 Windows FL Studio Producer Edition 21 v21.0.3 Build 3517 Windows/mac官方中文版是一个完整的软件音乐制作环境或数字音频工作站&#xff08;DAW&#xff09;。它代表了 25 多年的创新发展&#xff0c;将您创作、编曲、录…

剑指offer65.不用加减乘除做加法

把二进制加法可以分为五进位加法和进位加法&#xff0c;无进位&#xff1a;000&#xff0c;011&#xff0c;101&#xff0c;有进位加法&#xff1a;110进位为1。可以发现无进位的加法与异或运算规律相同&#xff0c;有进位加法和与运算规律相同&#xff0c;无进位和na^b,有进位…

【Spring Boot】(一)Spring Boot 项目的创建和使用

文章目录 前言一、什么是 Spring Boot1.1 初识 Spring Boot1.2 Spring Boot 的核心设计思想1.3 Spring Boot 的优点 二、Spring Boot 项目的创建2.1 使用 IDEA 创建2.2 使用网页创建2.3 项目的目录结构 三、Hello World3.1 运行启动类3.2 通过浏览器页面输出 Hello World3.3 约…

QT 使用单例模式

目录 1. 单例模式介绍 2.单例模式实现 1. 单例模式介绍 有些时候我们在做 qt 项目的时候,要用到很多类. 例如我们用到的类有 A,B,C,D. 其中,A 是 B,C,D 中都需要用到的类,A 类非常的抢手. 但是,A 类非常的占内存,定义一个 A 对象需要 500M 内存,假如在 B,C,D 中都定义一个 A 类…

pointpillars在Ubuntu2004训练的总结

1、找到pointpcdet-master之后在此打开终端输入code进入VScode界面 code 2、激活pp环境 conda activate pp 3、cd进入tools cd tools 4、将kitti数据集准备好放入data路径下之后开始训练 python train.py --cfg_file cfgs/kitti_models/pointpillar.yaml 5、训练完成之…

ComfyUI的一场线上辩论。

https://www.reddit.com/r/StableDiffusion/comments/15ilqso/hank_hill_tries_comfyui 从前有两个朋友&#xff0c;叫小明和小杰。一天&#xff0c;小明对小杰说&#xff1a;“我不知道node是什么意思。”小杰听了&#xff0c;觉得很好笑&#xff0c;他开玩笑地回答&#xff1…

手写一个简易的布隆过滤器

1.什么是布隆过滤器 布隆过滤器&#xff08;Bloom Filter&#xff09;是1970年由布隆(人名)提出的。它实际上是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。它的优点是空间效率和查询时间都比一般的算法要好的多&#xff0c;…

浏览器同源策略

浏览器同源策略 同源策略&#xff1a;是一个重要的浏览器的安全策略&#xff0c;用于限制一个源的文档或者它加载的脚本如何能与另一个源的资源进行交互 它能帮助阻隔恶意文档&#xff0c;减少可能被攻击的媒介 例如&#xff1a;被钓鱼网站收集信息&#xff0c;使用ajax发起…

Containerd的两种安装方式

1. 轻量级容器管理工具 Containerd 2. Containerd的两种安装方式 3. Containerd容器镜像管理 4. Containerd数据持久化和网络管理 操作系统环境为centos7u6 1. YUM方式安装 1.1 获取YUM源 获取阿里云YUM源 # wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun…

滇医通微信小程序分析笔记

注意 本文章仅供学习交流使用&#xff0c;如果你是铁粉你就会知道博主之前发布过一篇相关的文章&#xff0c;但是由于代码涉及到法律相关所以就隐藏了&#xff0c;两年的时间过去了&#xff0c;因为女朋友已经早早安排上了&#xff0c;所以就搁置了&#xff0c;本次不做代码分…

[国产MCU]-BL602开发实例-开发环境搭建

开发环境搭建 文章目录 开发环境搭建1、BL602介绍2、软件准备3、源码编译3.1 编译内置工程3.2 自定义工程、自定义组件添加与编译4、固件下载BL602 是一款Wi-Fi + BLE组合的芯片组,用于低功耗和高性能应用开发。无线子系统包含2.4G无线电,Wi-Fi 802.11b/g/n和BLE 5.0 基带/MA…

了解HTTP代理日志:解读请求流量和响应信息

嗨&#xff0c;爬虫程序员们&#xff01;你们是否在了解爬虫发送的请求流量和接收的响应信息上有过困扰&#xff1f;今天&#xff0c;我们一起来了解一下。 首先&#xff0c;我们需要理解HTTP代理日志的基本结构和内容。HTTP代理日志是对爬虫发送的请求和接收的响应进行记录的文…

MacOS上用docker运行mongo及mongo-express

MongoDB简介 MongoDB 是一个基于分布式文件存储的数据库。由 C 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。 MongoDB 是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xff0c;最像关系数据库的。 前提 要求…

AOP实现日志的打印

AOP面向切面编程&#xff0c;是一种抽象化的面向对象编程&#xff0c;也可以理解为对面向对象编程的补充 下面来举一个打印日志的例子 问题描述&#xff1a;写一个计算器的实现类&#xff0c;实现加减乘除功能&#xff0c;并在进行计算前日志输出方法&#xff0c;计算后输出结…