linux搭建minIO对象存储服务,springBoot整合

minIO 服务搭建

1. 创建安装目录

mkdir -p /usr/local/minio

2. 进入安装目录

cd /usr/local/minio

3.下载安装包 (wget 如果下载太慢,可以手动下载并上传安装包)

wget https://dl.minio.io/server/minio/release/linux-amd64/minio

在这里插入图片描述

4.创建数据存储文件夹

mkdir -p /usr/local/minio/data

5.编辑配置文件

vim /etc/default/minio

5.1 添加内容:用户名、密码、数据存储文件、程序链接端口、web界面访问端口

MINIO_ROOT_USER="minio"
MINIO_ROOT_PASSWORD="minio@123"
MINIO_VOLUMES=" /usr/local/minio/data"
MINIO_OPTS="--address 0.0.0.0:9000"
MINIO_OPTS1="--console-address 0.0.0.0:19001"

6.添加开机自启动配置

编辑配置文件文件

vim /etc/systemd/system/minio.service

添加配置文件内容 (主意启动器路径,自定义服务配置文件路径,以及连接端口要与配置文件里的对应)

[Unit]
Description=MinIO
Documentation=https://docs.min.io
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/minio/minio[Service]
WorkingDirectory=/usr/local/minio
ProtectProc=invisibleEnvironmentFile=/etc/default/minio
ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/default/minio\"; exit 1; fi"
ExecStart=/usr/local/minio/minio server --address 0.0.0.0:9000 $MINIO_OPTS  $MINIO_OPTS1 $MINIO_VOLUMES# Let systemd restart this service always
Restart=always# Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=65536# Specifies the maximum number of threads this process can create
TasksMax=infinity# Disable timeout logic and wait until process is stopped
TimeoutStopSec=infinity
SendSIGKILL=no[Install]
WantedBy=multi-user.target

7. 启动服务

#加载配置
systemctl daemon-reload
#添加启动器权限
chmod +x /usr/local/minio/minio
#启动minio
systemctl start minio.service
#开启开机自启
systemctl enable minio.service

查看服务

ps -ef |grep minio

在这里插入图片描述

8.验证服务

http://ip:19001/login

在这里插入图片描述
通过配置的账号密码登录
在这里插入图片描述

9.常用命令

systemctl start minio.service   #启动minio服务
systemctl stop minio.service   #停止minio服务
systemctl restart minio.service   #重新启动服务
systemctl status minio.service   #查看服务当前状态
systemctl enable minio.service   #设置开机自启动
systemctl disable minio.service   #停止开机自启动

10.目录

安装目录:/usr/local/minio
数据保存目录:/usr/local/minio/data
配置文件目录:/etc/default/minio
启动配置文件存放目录:vim /etc/systemd/system/minio.service

SpringBoot 整合

1.添加依赖

比较新的版本 最新到8.5.5 ,更多版本可以到maven仓库找
https://mvnrepository.com/artifact/io.minio/minio

        <!-- https://mvnrepository.com/artifact/io.minio/minio --><dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.3</version></dependency>

2.添加yml配置

minio:endpoint: http://127.0.0.1:9000 #Minio服务所在地址bucketName: test #存储桶名称accessKey: minioadmin #访问的keysecretKey: minioadmin #访问的秘钥

3.MinioConfig.class配置类

@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {private String endpoint;private String accessKey;private String secretKey;private String bucketName;@Beanpublic MinioClient minioClient() {return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();}
}

4.minio工具类

import com.alibaba.nacos.common.utils.UuidUtils;
import com.system.common.utils.RandomIdUtil;
import com.system.iotmanagement.config.MinioConfig;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriUtils;import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;@Component
@Slf4j
public class MinioUtil {@Autowiredprivate MinioConfig prop;@Resourceprivate MinioClient minioClient;/*** 查看存储bucket是否存在* @return boolean*/public Boolean bucketExists(String bucketName) {Boolean found;try {found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return found;}/*** 创建存储bucket* @return Boolean*/public Boolean makeBucket(String bucketName) {try {if (!bucketExists(bucketName)) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());String policyJson = "{\n" +"\t\"Version\": \""+new SimpleDateFormat("yyyy-mm-dd").format(System.currentTimeMillis())+"\",\n" +"\t\"Statement\": [{\n" +"\t\t\"Effect\": \"Allow\",\n" +"\t\t\"Principal\": {\n" +"\t\t\t\"AWS\": [\"*\"]\n" +"\t\t},\n" +"\t\t\"Action\": [\"s3:GetBucketLocation\", \"s3:ListBucket\", \"s3:ListBucketMultipartUploads\"],\n" +"\t\t\"Resource\": [\"arn:aws:s3:::" + bucketName + "\"]\n" +"\t}, {\n" +"\t\t\"Effect\": \"Allow\",\n" +"\t\t\"Principal\": {\n" +"\t\t\t\"AWS\": [\"*\"]\n" +"\t\t},\n" +"\t\t\"Action\": [\"s3:AbortMultipartUpload\", \"s3:DeleteObject\", \"s3:GetObject\", \"s3:ListMultipartUploadParts\", \"s3:PutObject\"],\n" +"\t\t\"Resource\": [\"arn:aws:s3:::" + bucketName + "/*\"]\n" +"\t}]\n" +"}\n";minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(policyJson).build());log.info("buckets:【{}】,创建[readwrite]策略成功!", bucketName);} else {log.info("minio bucket->>>【{}】already exists", bucketName);}} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 删除存储bucket* @return Boolean*/public Boolean removeBucket(String bucketName) {try {minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());} catch (Exception e) {e.printStackTrace();return false;}return true;}/*** 获取全部bucket*/public List<Bucket> getAllBuckets() {try {List<Bucket> buckets = minioClient.listBuckets();return buckets;} catch (Exception e) {e.printStackTrace();}return null;}/*** 文件上传** @param file 文件* @return Boolean*/public String upload(MultipartFile file) {String originalFilename = file.getOriginalFilename();if (StringUtils.isBlank(originalFilename)){throw new RuntimeException();}String fileName = UuidUtils.generateUuid() + originalFilename.substring(originalFilename.lastIndexOf("."));String objectName = RandomIdUtil.getyyyyMMddString() + "/" + fileName;try {PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(prop.getBucketName()).object(objectName).stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();//文件名称相同会覆盖minioClient.putObject(objectArgs);} catch (Exception e) {e.printStackTrace();return null;}return  objectName;}/*** 预览图片* @param fileName* @return*/public String preview(String fileName){// 查看文件地址GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(prop.getBucketName()).object(fileName).method(Method.GET).build();try {String url = minioClient.getPresignedObjectUrl(build);return url;} catch (Exception e) {e.printStackTrace();}return null;}/*** 文件下载* @param fileName 文件名称* @param res response* @return Boolean*/public void download(String fileName, HttpServletResponse res) {GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(prop.getBucketName()).object(fileName).build();try (GetObjectResponse response = minioClient.getObject(objectArgs)){byte[] buf = new byte[1024];int len;try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()){while ((len=response.read(buf))!=-1){os.write(buf,0,len);}os.flush();byte[] bytes = os.toByteArray();res.setCharacterEncoding("utf-8");// 设置强制下载不打开// res.setContentType("application/force-download");res.addHeader("Content-Disposition", "attachment;fileName=" + UriUtils.encode(fileName, StandardCharsets.UTF_8));try (ServletOutputStream stream = res.getOutputStream()){stream.write(bytes);stream.flush();}}} catch (Exception e) {e.printStackTrace();}}/*** 查看文件对象* @return 存储bucket内文件对象信息*/public List<Item> listObjects() {Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(prop.getBucketName()).build());List<Item> items = new ArrayList<>();try {for (Result<Item> result : results) {items.add(result.get());}} catch (Exception e) {e.printStackTrace();return null;}return items;}/*** 删除* @param fileName* @return* @throws Exception*/public boolean remove(String fileName){try {minioClient.removeObject( RemoveObjectArgs.builder().bucket(prop.getBucketName()).object(fileName).build());}catch (Exception e){return false;}return true;}
}

生成时间字符串的工具类,(可以自己另外引用其他的)

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;public class RandomIdUtil {/*** 生成随机ID:当前年月日时分秒毫秒 +五位随机数*/public static String getRandomID(String businessCode) {String str  = new SimpleDateFormat("yyyyMMddHHmmssSS").format(new Date());Random random = new Random();int rannum = (int) (random.nextDouble() * (99999 - 10000 + 1)) + 10000;// 获取5位随机数return businessCode+str + rannum;// 当前时间}public static String getyyyyMMddHHString() {return new SimpleDateFormat("yyyyMMddHH").format(new Date());}public static String getyyyyMMddString() {return new SimpleDateFormat("yyyyMMdd").format(new Date());}}

5. 文件处理接口

@Api(tags = "文件相关接口")
@Slf4j
@RestController
@RequestMapping(value = "product/file")
public class FileController {@Autowiredprivate MinioUtil minioUtil;@Autowiredprivate MinioConfig prop;@ApiOperation(value = "查看存储bucket是否存在")@GetMapping("/bucketExists")public R bucketExists(@RequestParam("bucketName") String bucketName) {return R.ok().put("bucketName",minioUtil.bucketExists(bucketName));}@ApiOperation(value = "创建存储bucket")@GetMapping("/makeBucket")public R makeBucket(String bucketName) {return R.ok().put("bucketName",minioUtil.makeBucket(bucketName));}@ApiOperation(value = "删除存储bucket")@GetMapping("/removeBucket")public R removeBucket(String bucketName) {return R.ok().put("bucketName",minioUtil.removeBucket(bucketName));}@ApiOperation(value = "获取全部bucket")@GetMapping("/getAllBuckets")public R getAllBuckets() {List<Bucket> allBuckets = minioUtil.getAllBuckets();return R.ok().put("allBuckets",allBuckets);}@ApiOperation(value = "文件上传返回url")@PostMapping("/upload")public R upload(@RequestParam("file") MultipartFile file) {String objectName = minioUtil.upload(file);if (null != objectName) {return R.ok().put("url",(prop.getEndpoint() + "/" + prop.getBucketName() + "/" + objectName));}return R.error();}@ApiOperation(value = "图片/视频预览")@GetMapping("/preview")public R preview(@RequestParam("fileName") String fileName) {return R.ok().put("filleName",minioUtil.preview(fileName));}@ApiOperation(value = "文件下载")@GetMapping("/download")public R download(@RequestParam("fileName") String fileName, HttpServletResponse res) {minioUtil.download(fileName,res);return R.ok();}@ApiOperation(value = "删除文件", notes = "根据url地址删除文件")@PostMapping("/delete")public R remove(String url) {String objName = url.substring(url.lastIndexOf(prop.getBucketName()+"/") + prop.getBucketName().length()+1);minioUtil.remove(objName);return R.ok().put("objName",objName);}}

基本操作和可能遇到的问题

1.存储bucket 的两种方式

1.客户端手动创建
在这里插入图片描述
2.代码创建,见工具类和接口方法

可能遇到的问题

当文件上传之后比如一张图片,直接通过图片路径访问报一下错误
在这里插入图片描述
这是因为浏览器打开没有权限
解决办法,默认显示的是n/a,设置minio代理权限,选择对应的桶,将其代理权限也设置为公有
在这里插入图片描述
就可以成功访问了

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

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

相关文章

恒流电路的三种设计方案

作为硬件研发工程师相信对恒流电路不会陌生&#xff0c;本文介绍下三种恒流电路的原理图。 三极管恒流电路 三极管恒流电路 三极管的恒流电路&#xff0c;主要是利用Q2三极管的基级导通电压为0.6~0.7V这个特性&#xff1b;当Q2三极管导通&#xff0c;Q1三极管基级电压被拉低而…

大数据课程K12——Spark的MLlib概述

文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 了解Spark的MLlib概念; ⚪ 掌握Spark的MLlib基本数据模型; ⚪ 掌握Spark的MLlib统计量基础; 一、Spark MLlib介绍 1. 概述 MLlib是Apache Spark的可迭代机器学习库。 2. 易于使用 …

【优选算法】—— 二分查找

序言&#xff1a; 本期&#xff0c;我们将要介绍的是有关 二分查找算法 并通过题目帮组大家更好的理解&#xff01; 目录 &#xff08;一&#xff09;基本介绍 1、基本思想 2、解题流程 3、复杂度以及注意事项 &#xff08;二&#xff09;题目讲解 1、在排序数组中查找…

Sql Server导出数据库到另一个数据库

1.打开sql server数据库&#xff0c;连接到服务器后&#xff0c;找到需要导出的数据库&#xff0c;右击后选择 任务->导出数据。 2.点击 下一步。 3.身份验证可以使用SQL Server身份验证&#xff0c;就是当时建立连接时的用户名和密码&#xff0c;数据库名称使用默认的&…

C++实现YOLOP

C实现YOLOP 一、简介 使用OpenCV部署全景驾驶感知网络YOLOP&#xff0c;可同时处理交通目标检测、可驾驶区域分割、车道线检测&#xff0c;三项视觉感知任务&#xff0c;依然是包含C和Python两种版本的程序实现 onnx文件从百度云盘下载&#xff0c;链接&#xff1a;https://…

<C++> STL_deque

<c> STL_deque 1.deque的使用 deque(双端队列)&#xff1a;是一种双开口的"连续"空间的数据结构&#xff0c;双开口的含义是&#xff1a;可以在头尾两端进行插入和 删除操作&#xff0c;且时间复杂度为O(1)&#xff0c;与vector比较&#xff0c;头插效率高&a…

一生一芯9——ubuntu22.04安装valgrind

这里安装的valgrind版本是3.19.0 下载安装包 在选定的目录下打开终端&#xff0c;输入以下指令 wget https://sourceware.org/pub/valgrind/valgrind-3.19.0.tar.bz2直至下载完成 解压安装包 输入下面指令解压安装包 tar -xvf valgrind-3.19.0.tar.bz2.tar.bz2注&#xf…

Keepalived+Lvs(dr)调度器主备配置小实验

目录 前言 一、实验拓扑图 二、配置LVS&#xff08;dr&#xff09;模式 三、配置调配器热备 四、测试 总结 前言 Keepalived和LVS&#xff08;Linux Virtual Server&#xff09;是两个常用的开源软件&#xff0c;通常结合使用以提供高可用性和负载均衡的解决方案。 Keepalive…

身为程序员,你有哪些提高写代码效率的工具?

首先&#xff0c;每个程序员都是会利用工具的人&#xff0c;也有自己囊里私藏的好物。独乐乐不如众乐乐&#xff0c;今天笔者整理了3个辅助我们写代码的黑科技&#xff0c;仅供参考。如果你有更好的工具&#xff0c;欢迎评论区分享。 1、Google/Stackoverflow——搜索解决方案的…

【运维】linux安装oracle客户端、安装mysql

文章目录 一. 下载二. 配置1. 配置环境变量2. 配置tnsnames.ora文件 三. 测试1. 链接语法2. 连接测试 四. 通过rpm安装mysql 一. 下载 下载地址 基础包 连接工具 二. 配置 上传、解压、配置环境变量 这里安装在/data01目录下 unzip instantclient-sqlplus-linux.x64-19.2…

Spring Boot(Vue3+ElementPlus+Axios+MyBatisPlus+Spring Boot 前后端分离)【三】

&#x1f600;前言 本篇博文是关于Spring Boot(Vue3ElementPlusAxiosMyBatisPlusSpring Boot 前后端分离)【三】的分享&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我…

keepalived+lvs(DR)

目录 一、作用 二、安装 1、在192.168.115.3 和192.168.115.4 上安装ipvs和keepalived&#xff1a; 2、配置keepalived 3、查看lvs节点状态 4、web节点配置 5、在web节点上调整ARP参数 6、配置虚拟IP地址与添加回环路由 7、配置nginx网页文档 8、启动服务 9、测试 一…

上位机采集8通道模拟量模块数据

模拟量模块和上位机的配合使用可以实现对模拟量数据的采集、传输和处理。下面是它们配合使用的一般步骤&#xff1a;1. 连接模拟量模块&#xff1a;将模拟量模块与上位机进行连接。这通常涉及将模拟量模块的输入通道与被监测的模拟信号源连接起来&#xff0c;如传感器、变送器等…

14. Docker中实现CI和CD

目录 1、前言 2、什么是CI/CD 3、部署Jenkins 3.1、下载Jenkins 3.2、启动Jenkins 3.3、访问Jenkins页面 4、Jenkins部署一个应用 5、Jenkins实现Docker应用的持续集成和部署 5.1、创建Dockerfile 5.2、集成Jenkins和Docker 6、小结 1、前言 持续集成(CI/CD)是一种…

18-使用钩子函数判断用户登录权限-登录前缀

钩子函数的两种应用: (1). 应用在app上 before_first_request before_request after_request teardown_request (2). 应用在蓝图上 before_app_first_request #只会在第一次请求执行,往后就不执行, (待定,此属性没调试通过) before_app_request # 每次请求都会执行一次(重点…

【Three.js + Vue 构建三维地球-Part One】

Three.js Vue 构建三维地球-Part One Vue 初始化部分Vue-cli 安装初始化 Vue 项目调整目录结构 Three.js 简介Three.js 安装与开始使用 实习的第一个任务是完成一个三维地球的首屏搭建&#xff0c;看了很多的案例&#xff0c;也尝试了用 Echarts 3D地球的模型进行构建&#xf…

设计模式中的关系

文章目录 一、依赖概念 二&#xff0c;关联概念 三、聚合概念 四、组合概念 五、实现概念 六、继承概念 图总结整体总结 一、依赖 概念 依赖是一种临时使用关系&#xff0c;代码层体现为作为参数。 具体体现&#xff1a;依赖者调用被依赖者的局部变量、参数、静态方法&#…

docker项目实战

目录 1、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘。 1&#xff09;拉取mysql:5.6和owncloud镜像 2&#xff09;后台运行容器 3&#xff09;通过ip:端口的方式访问owncloud 2、安装搭建私有仓库 Harbor 1&#xff09;首先准备所需包 2&#xff09;安装h…

Lua与C++交互(一)————堆栈

Lua与C交互&#xff08;一&#xff09;————堆栈 Lua虚拟机 什么是Lua虚拟机 Lua本身是用C语言实现的&#xff0c;它是跨平台语言&#xff0c;得益于它本身的Lua虚拟机。 虚拟机相对于物理机&#xff0c;借助于操作系统对物理机器&#xff08;CPU等硬件&#xff09;的一…

HTML番外篇(四)-HTML5新增元素-CSS常见函数-理解浏览器前缀-BFC

一、HTML5新增元素 1.HTML5语义化元素 在HMTL5之前&#xff0c;我们的网站分布层级通常包括哪些部分呢&#xff1f; header、nav、main、footer ◼ 但是这样做有一个弊端&#xff1a; 我们往往过多的使用div, 通过id或class来区分元素&#xff1b;对于浏览器来说这些元素不…