MinIO - 从 环境搭建 -> SpringBoot实战 -> 演示,掌握 Bucket 和 Object 操作

目录

开始

Docker 部署

MinIO 中的基本概念

SpringBoot 集成 MinIO

依赖

配置

MinIO 时间差问题报错 The difference between the request time and the server`s time is too large

MinIO 中对 Bucket(文件夹) 的操作

是否存在 / 创建

查询所有文件夹

删除文件夹

MinIO 中对 Object(文件) 的操作

两种文件上传的方式

查看文件状态(是否存在)

生成带签名的URL路径

怎么使用不带签名的 url 直接访问

从 MinIO 上获取图片,然后下载到本地磁盘'

获取文件夹下的所有文件


开始


Docker 部署

a)拉取镜像

docker pull minio/minio

 b)创建挂载点

mkdir -p ~/env/minio/conf
mkdir -p ~/env/minio/data

 c)运行

这里设置了 MinIO 的用户名和密码,注意密码不能少于 8 位

docker run -d \
--name minio \
-p 9000:9000 \
-p 9001:9001 \
--privileged=true \
-e "MINIO_ROOT_USER=root" \
-e "MINIO_ROOT_PASSWORD=rootroot" \
-v ~/env/minio/data:/data \
-v ~/env/minio/conf:/root/.minio \
minio/minio server \
--console-address ":9000" \
--address ":9001" /data

 d)访问:http://env-base:9000

MinIO 中的基本概念

Bucket:相当于存放文件的文件夹,用来存储 Object 的逻辑空间.

Object:相当于文件,是存储到 MinIO 中的基本对象.

Ps:Minio 存在线程安全问题么?

Minio 是线程安全的,即使在 SpringBoot 中 Bean 是使用单例模式的(作者在 github 上的回复).

SpringBoot 集成 MinIO

依赖

Note:官网地址 Software Development Kits (SDK) — MinIO Object Storage for Linux

Maven 如下 

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

Gradle 如下

dependencies {
    implementation("io.minio:minio:8.5.11")
}

配置

由于 MinIO 没有 SpringBootStarter 相关的依赖,因此配置类需要我们自己来写~

import io.minio.MinioClient
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration

@Configuration
class MinioConfig {

    @Bean
    fun minioClient(): MinioClient = MinioClient.builder()
        .endpoint("http://100.105.180.32:9001") //格式必须是 http://ip:port  注意: 这里使用的 9001 端口,而不是 9000
        .credentials("root", "rootroot") //用户名 和 密码
        .build()

}

MinIO 时间差问题报错 The difference between the request time and the server`s time is too large

如果出现了上述报错,说明你的主机和服务器上的时间不一致.

解决如下:

a)下载 ntpdate,用来同步主机和服务器的时间.

yum install ntpdate -y

b)同步时间,如下命令

ntpdate pool.ntp.org

MinIO 中对 Bucket(文件夹) 的操作

是否存在 / 创建

案例:如果不存在 dir1 文件夹,就创建.

@SpringBootTest
class MinioApplicationTests {

    @Resource
    private lateinit var minioClient: MinioClient

    /**
     * 如果文件夹 dir1 不存在就创建
     */
    @Test
    fun test1() {
        val exists = minioClient.bucketExists(
            BucketExistsArgs.builder()
                .bucket("dir1")
                .build()
        )
        if (!exists) {
            minioClient.makeBucket(
                MakeBucketArgs.builder()
                    .bucket("dir1")
                    .build()
            )
        } else {
            println("文件夹已经存在!")
        }
    }

}

 第一次运行,可以看到会创建出这个文件夹:

第二次运行就会进行提示:

查询所有文件夹

如下代码:

    @Test
    fun test2() {
        val bucketList = minioClient.listBuckets()
        bucketList.forEach { bucket ->
            println("${bucket.name()} -- ${bucket.creationDate()}")
        }
    }

现在 MinIO 上有两个文件夹,如下: 

运行结果如下:

删除文件夹

案例:删除文件夹 dir2

    @Test
    fun test3() {
        minioClient.removeBucket(
            RemoveBucketArgs.builder()
                .bucket("dir2")
                .build()
        )
    }

MinIO 中对 Object(文件) 的操作

两种文件上传的方式

案例:将本地 "D:/tmp/滑稽.gif" 图片上传到 MinIO 的 "dir1" 文件夹下,并重命名为 "test.gif" 

a)stream 方式

    @Test
    fun test1() {
        val file = File("D:/tmp/滑稽.gif")
        minioClient.putObject(
            PutObjectArgs.builder()
                .bucket("dir1")
                .`object`("test.gif")
                //stream:
                //第二个参数(long objectSize): 要上传的文件大小
                //第三个参数(long partSize): 指定缓冲区的大小
                //这两个如果不知道,都可以使用 -1
                .stream(FileInputStream(file), file.length(), -1)
                .build()
        )
    }

b) upload 方式(更简单一些)

    @Test
    fun test2() {
        minioClient.uploadObject(
            UploadObjectArgs.builder()
                .bucket("dir1")
                .`object`("test.gif")
                .filename("D:/tmp/滑稽.gif")
                .build()
        )
    }

 c)运行结果在 MinIO 上可以观察到:

相比较上面的上传文件的方式,以下这种上传文件的方式就更加简单

查看文件状态(是否存在)

案例:查询 "dir1" 文件夹下的 "test.gif" 文件的状态

    @Test
    fun test3() {
        val result = minioClient.statObject(
            StatObjectArgs.builder()
                .bucket("dir1")
                .`object`("test.gif")
                .build()
        )
        println(result)
    }

a)如果文件存在,运行结果如下:

b)如果文件不存在,抛出异常如下:

c)对于文件不存在的情况,也可以做出如下处理

    @Test
    fun test3() {
        try {
            val result = minioClient.statObject(
                StatObjectArgs.builder()
                    .bucket("dir1")
                    .`object`("testa1.gif")
                    .build()
            )
            println(result)
        } catch (e: ErrorResponseException) {
            println("文件不存在!")
            println(e.message)
        }

    }

 运行结果如下:

生成带签名的URL路径

案例:给 MinIO 上的 "dir1" 文件夹下的 "test.gif" 文件生成一个带签名的 url 路径(get 请求).

    @Test
    fun test4() {
        val url = minioClient.getPresignedObjectUrl(
            GetPresignedObjectUrlArgs.builder()
                .bucket("dir1")
                .`object`("test.gif")
                .method(Method.GET) //指定生成的 url 请求方式
                // .expiry(3, TimeUnit.SECONDS) 设置签名的过期时间
                .build()
        )
        println(url)
    }

运行结果如下:

通过这个 url 就可以访问到图片

怎么使用不带签名的 url 直接访问

a)后台修改

下图位置,可以设置成 public 的,这样就可以通过不带签名的 url 直接访问到图片.

这样所有用户都能访问这个图片.

值得注意的是,如果设置成 public,会比较危险,因为这样意味着所有用户都能对这个桶下的文件进行 增删改查...

不过也可以给这个文件夹赋予只读权限(只有登录了 MinIO 的用户才能进行其他操作,比如你的程序最开始配置了 MinioClient,才可以进行其他操作):

再返回来,就可以看到该文件夹自动变成了自定义的权限:

打开就可以看到给你自动生成的 json 文件来实现针对 url 的只读权限控制:

b)创建桶的时候指定访问策略(只允许读操作)

Ps:代码中的 jsonConfig 就是从第一种方式中生成的 json 文件复制过来就可以,但是注意要修改以下文件名!

    @Test
    fun test5() {
        //新建文件夹 dir2
        minioClient.makeBucket(
            MakeBucketArgs.builder()
                .bucket("dir2")
                .build()
        )

        //设置文件夹的访问权限为 只读
        val jsonConfig = """
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "*"
                ]
            },
            "Action": [
                "s3:GetBucketLocation"
            ],
            "Resource": [
                "arn:aws:s3:::dir2"
            ]
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "*"
                ]
            },
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::dir2"
            ],
            "Condition": {
                "StringEquals": {
                    "s3:prefix": [
                        "*"
                    ]
                }
            }
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "*"
                ]
            },
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::dir2/**"
            ]
        }
    ]
}
        """.trimIndent()

        minioClient.setBucketPolicy(
            SetBucketPolicyArgs.builder()
                .bucket("dir2")
                .config(jsonConfig)
                .build()
        )

        //上传图片
        minioClient.uploadObject(
            UploadObjectArgs.builder()
                .bucket("dir2")
                .`object`("test.gif")
                .filename("D:/tmp/滑稽.gif")
                .build()
        )

        val url = minioClient.getPresignedObjectUrl(
            GetPresignedObjectUrlArgs.builder()
                .bucket("dir2")
                .`object`("test.gif")
                .method(Method.GET)
                .build()
        ).split("?")[0] //这样就可以不需要 签名 部分了
        println(url)
    }

运行结果如下: 

 

之后就可以直接不带 签名档 url 通过 url 来访问啦~

从 MinIO 上获取图片,然后下载到本地磁盘'

案例:获取 文件夹"dir1" 中的 "test.gif"文件 ,保存到本地磁盘的 "D:/tmp/" 路径下,并重命名为 "123.gif"

    @Test
    fun test6() {
        val resp = minioClient.getObject(
            GetObjectArgs.builder()
                .bucket("dir1")
                .`object`("test.gif")
                .build()
        )
        val file = FileOutputStream("D:/tmp/123.gif")
        val result = resp.transferTo(file)
        println(result)
    }

 运行结果如下:

获取文件夹下的所有文件

案例:获取 dir1 文件夹下的所有文件名

    @Test
    fun test7() {
        val objects = minioClient.listObjects(
            ListObjectsArgs.builder()
                .bucket("dir1")
                .build()
        )
        objects.forEach { result ->
            val item = result.get()
            println(item.objectName())
        }
    }

 运行结果如下:

删除文件

案例:删除文件夹 "dir1" 中的 test2.jpg 文件.

    @Test
    fun test8() {
        minioClient.removeObject(
            RemoveObjectArgs.builder()
                .bucket("dir1")
                .`object`("test2.jpg")
                .build()
        )
    }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

图像处理调试软件推荐

对于图像处理的调试&#xff0c;使用具有图形用户界面&#xff08;GUI&#xff09;且支持实时调整和预览的图像处理软件&#xff0c;可以大大提高工作效率。以下是几款常用且功能强大的图像处理调试软件推荐&#xff1a; ImageJ/FijiMATLABOpenCV with GUI LibrariesNI Vision …

绝了,华为伸缩摄像头如何突破影像边界?

自华为Pura70 Ultra超聚光伸缩镜头诞生以来&#xff0c;备受大家的关注&#xff0c;听说这颗镜头打破了传统手机的摄像头体积与镜头的设计&#xff0c;为我们带来了不一样的拍照体验。 智能手机飞速发展的今天&#xff0c;影像功能已经成为我们衡量一款手机性能的重要指标。想…

Mac|install vue

安装Node&#xff1a;Node.js — Download Node.js 选择系统为mac&#xff0c;安装步骤在终端输入 &#xff08;放文字版在这里&#xff5e;方便复制&#xff09; # installs nvm (Node Version Manager) curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/ins…

【TB作品】数码管独立按键密码锁,ATMEGA16单片机,Proteus仿真 atmega16数码管独立按键密码锁

文章目录 基于ATmega16的数码管独立按键密码锁设计实验报告实验背景硬件介绍主要元器件电路连接 设计原理硬件设计软件设计 程序原理延时函数独立按键检测密码显示主函数 资源代码 基于ATmega16的数码管独立按键密码锁设计实验报告 实验背景 本实验旨在设计并实现一个基于ATm…

ctfshow web入门 web338--web344

web338 原型链污染 comman.js module.exports {copy:copy };function copy(object1, object2){for (let key in object2) {if (key in object2 && key in object1) {copy(object1[key], object2[key])} else {object1[key] object2[key]}}}login.js var express …

c/c++ 程序运行的过程分析

c/c编译基础知识 GNU GNU&#xff08;GNU’s Not Unix!&#xff09;是一个由理查德斯托曼&#xff08;Richard Stallman&#xff09;在1983年发起的自由软件项目&#xff0c;旨在创建一个完全自由的操作系统&#xff0c;包括操作系统的内核、编译器、工具、库、文本编辑器、邮…

深度网络现代实践 - 深度前馈网络之反向传播和其他的微分算法篇

序言 反向传播&#xff08;Backpropagation&#xff0c;简称backprop&#xff09;是神经网络训练过程中最关键的技术之一&#xff0c;尤其在多层神经网络中广泛应用。它是一种与优化方法&#xff08;如梯度下降法&#xff09;结合使用的算法&#xff0c;用于计算网络中各参数的…

前端正悄悄蚕食后端开发者的工作,这真的好吗?

**前端正悄悄蚕食后端开发者的工作&#xff0c;这真的好吗&#xff1f;** 前端开发者的职责范围正在逐渐扩大。从最初的单纯页面设计&#xff0c;到现在的与后端数据交互、应用逻辑处理等&#xff0c;前端开发者在项目中的作用日益重要。与此同时&#xff0c;这也引发了一个值…

固态,机械,移动(U盘),sd卡,哪个更适合长期储存数据 保存数据用什么硬盘可靠 硬盘数据丢失怎么找回 硬盘维护注意事项

有关硬盘数据丢失的恢复技巧&#xff0c;这篇文章一定要收藏好。在硬盘使用过程中&#xff0c;很多情况都会导致数据丢失&#xff0c;例如硬盘跌落、病毒感染、系统文件损坏等。这时候&#xff0c;一定要采用正确的方法&#xff0c;抢救硬盘中存储的珍贵数据和文档。 有关长期保…

技术实现路径怎么写?(Word项目技术路径文档参考)

软件项目编写技术实现路径至关重要&#xff0c;因为它为项目团队提供了清晰的开发蓝图。这一路径明确了从项目启动到交付各阶段所需的技术方案、步骤及预期成果&#xff0c;有助于团队统一认识&#xff0c;确保开发工作有序进行。同时&#xff0c;技术实现路径有助于识别潜在的…

ELK优化之Filebeat部署

目录 1.安装配置Nginx 2.安装 Filebeat 3.设置 filebeat 的主配置文件 4.修改Logstash配置 5.启动配置 6.kibana验证 主机名ip地址主要软件es01192.168.9.114ElasticSearches02192.168.9.115ElasticSearches03192.168.9.116ElasticSearch、Kibananginx01192.168.9.113ng…

Docker(二):Docker image Docker Container

本文将介绍 Docker 映像和容器以及 docker 文件之间的差异与联系&#xff0c;本文还将解释如何以及何时使用它们。 什么是 Dockerfile&#xff1f; 它是一个简单的文本文件&#xff0c;包含命令或过程的集合。我们运行的这些命令和准则作用于配置为创建新的 Docker 镜像的基本…

G1.【C语言】EasyX初步了解

1.介绍 EasyX 是针对 C/C 的图形库&#xff0c;可以帮助使用C/C语言的程序员快速上手图形和游戏编程。 2.安装 EasyX Graphics Library for CEasyX Graphics Library 是针对 Visual C 的绘图库&#xff0c;支持 VC6.0 ~ VC2019&#xff0c;简单易用&#xff0c;学习成本极低…

轻预压:滚珠丝杆精度与刚性的平衡点!

预压是指在所需的工作负荷下&#xff0c;使滚珠丝杆预先承受一定的负荷&#xff0c;从而使滚珠丝杆的轴向向心度和侧向偏差达到较小的偏差范围&#xff0c;保证了滚珠丝杆的准确性和稳定性&#xff0c;也确保机器的高精度和长期运作的可靠性。 预压是滚珠丝杆设计中的一个重要参…

vue3项目图片压缩+rem+自动重启等plugin使用与打包配置

一、Svg配置 每次引入一张 SVG 图片都需要写一次相对路径&#xff0c;并且对 SVG 图片进行压缩优化也不够方便。 vite-svg-loader插件加载SVG文件作为Vue组件&#xff0c;使用SVGO进行优化。 插件网站https://www.npmjs.com/package/vite-svg-loader 1. 安装 pnpm i vite-svg…

智能与伦理:Kimi与学术道德的和谐共舞

学境思源&#xff0c;一键生成论文初稿&#xff1a; AcademicIdeas - 学境思源AI论文写作 Kimi&#xff0c;由月之暗面科技有限公司开发的智能助手&#xff0c;擅长中英文对话&#xff0c;能处理多种文档和网页内容。在论文写作中&#xff0c;Kimi可提供资料查询、信息整理、语…

JavaWeb--jquery篇

概述 jQuery是一个快速、简洁的JavaScript框架&#xff0c;是一个优秀的JavaScript代码库&#xff08;框架&#xff09;于2006年1月由John Resig发布。它封装JavaScript常用的功能代码&#xff0c;提供一种简便的JavaScript设计模式&#xff0c;优化HTML文档操作、事件处理、动…

Faster-RCNN·代码解读系列01:Selective Search 和 R-CNN、Fast-CNN 简介

Selective Search 和 R-CNN、Fast-CNN 简介 1 目标检测算法简介1.0滑窗法的思路1.1 Selective Search 和 R-CNN 简介1.2.1 Selective Search简介1.1.1 Selective Search的思路1.1.2 Selective Search图解 1.2 Selective Search 和 Fast-CNN简介1.2.1 SPP和ROI Pooling简介1.2.2…

高级计算机体系结构--期末教材复习

Chap2 性能评测和并行编程性能评测并行编程为什么需要三次 barrier改进方法 Chap3 互连网络交换和路由二维网格中 XY 路由 死锁、活锁及饿死死锁避免的方法&#xff1a;虚通道、转弯模型二维网格中最小 西向优先、北向最后和负向优先算法转弯模型&#xff1a;超立方体的部分自适…

原生JavaScript实现录屏功能

1. 前言 使用JavaScript实现浏览器中打开系统录屏功能 示例图: 2. 源码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><meta http-equiv"X-UA-Compatible" content"IEedge" /><…