MinIO基本使用(实现上传、下载功能)

news2024/11/17 4:50:47

MinIO基本使用(实现上传、下载功能)

  • 1.简介
  • 2.下载和安装
  • 3.启动服务端
  • 4.创建User和Bucket
    • 4.1 创建User
      • 4.1.1 生成accessKey和secretKey
    • 4.2 创建Bucket
  • 5.在SpringBoot中使用MinIO
    • 5.1 引入依赖
    • 5.2 配置文件定义
    • 5.3 定义实体类
    • 5.4 定义业务类
    • 5.5 定义测试类
    • 5.6 测试
      • 5.6.1 上传
      • 5.6.2 下载

1.简介

MinIO是一款基于Go语言发开的高性能、分布式的、开源的对象存储系统。兼容亚马逊的S3协议,对Kubernetes能够友好的支持,专为AI等云原生工作负载而设计。

2.下载和安装

中文官网的下载会出现404错误,直接去英文官网进行下载即可。下载地址如下。

服务端:https://dl.minio.io/server/minio/release/windows-amd64/minio.exe

客户端:https://dl.minio.io/client/mc/release/windows-amd64/mc.exe

3.启动服务端

将安装好的服务端程序放置在D盘下的MinIO文件夹下。
在这里插入图片描述
打开cmd窗口输入命令

minio.exe server D:\MinIO

在这里插入图片描述
minio.exe是服务端程序的可执行程序,server表示启动MinIO服务器的模式,D:\MinIO表示是本地文件系统中的一个目录,MinIO服务器将在这个目录中存储数据。

在上面的D:\MinIO文件夹下有一个bucket-test文件夹就是我创建的一个bucket,其中有测试上传的数据。

启动server之后输入本地的ip加默认端口9000即可访问minio的服务端管理网页。

4.创建User和Bucket

4.1 创建User

点击左侧导航栏的Identity下的User,然后右上角点击create user
在这里插入图片描述
在这里插入图片描述
创建好用户并且设置密码,策略选择consoleAdmin,然后点击save按钮。之后也可以使用该用户名和密码登录控制台。

4.1.1 生成accessKey和secretKey

创建好用户之后,点击名称进入。
在这里插入图片描述
依次选择Service Accounts,Create Access Key来创建accessKey和secretKey。
在这里插入图片描述
点击Create
在这里插入图片描述
再点击Download for import,保存生成的密钥。

注意: 该密钥只会展示一次,切记下载好密钥文件,或者复制粘贴到文本文档中保存。

在这里插入图片描述

4.2 创建Bucket

点击左侧导航栏Buckets,再点击右上角Create Bucket
在这里插入图片描述

按照命名格式要求输入Bucket的名称,再点击Create Bucket按钮即可创建好Bucket。
在这里插入图片描述

5.在SpringBoot中使用MinIO

5.1 引入依赖

在pom.xml中引入下面依赖

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

5.2 配置文件定义

定义一个minio.properties的配置文件,配置好连接minio的一些参数。
在这里插入图片描述

minio.endpoint=http://127.0.0.1:9000
minio.accessKey=eBocSyvafvzTwUqi
minio.secretKey=9zBut31aOFTj6MDSnFZIT4fQfR8uwq3U

minio.endpoint是连接的url
minio.accessKey和minio.secretKey是4.1.1节保存的accessKey和secretKey

5.3 定义实体类

定义MinioConfig类映射配置文件的参数。并且根据定义好的参数创建一个MinioClient类的Bean对象。

@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
@PropertySource(value = "classpath:minio.properties")
public class MinioConfig {
    private String endpoint;

    private String accessKey;

    private String secretKey;

    @Bean
    public MinioClient minioClient() {
        return MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
    }
}

5.4 定义业务类

定义业务接口FileService,定义上传、下载、列出对象、删除文件四个方法

public interface FileService {
    /**
     * 上传
     *
     * @param file   文件
     * @param bucket bucket
     */
    void upload(MultipartFile file, String bucket);

    /**
     * 下载
     *
     * @param fileName 文件名
     * @param delete   删除
     * @param response 响应
     * @param bucket   bucket
     */
    void download(String bucket, String fileName, boolean delete, HttpServletResponse response);

    /**
     * 列出对象
     *
     * @param bucket bucket
     * @param prefix 前缀
     * @return {@link List}<{@link ObjectItem}>
     */
    List<ObjectItem> listObjects(String bucket, String prefix);

    /**
     * 删除文件
     *
     * @param bucket   bucket
     * @param fileName 文件名称
     */
    void removeFile(String bucket, String fileName);
}

定义实现类FileServiceImpl

@Service
@Slf4j
public class FileServiceImpl implements FileService {
    @Resource
    private MinioClient minioClient;

    @Override
    public void upload(MultipartFile file, String bucket) {
        String fileName = FileUtils.extractUploadFileName(file);
        try {
            boolean exist = minioClient.bucketExists(BucketExistsArgs.builder()
                    .bucket(bucket)
                    .build());
            if (!exist) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
            }
            InputStream inputStream = file.getInputStream();
            // 上传到minio服务器
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucket)
                    .object(fileName)
                    .stream(inputStream, -1L, 10485760L)
                    .build());
        } catch (Exception e) {
            log.error(fileName + "上传失败");
        }
    }

    @Override
    public void download(String bucket, String fileName, boolean delete, HttpServletResponse response) {
        try {
            if (StringUtils.isBlank(fileName)) {
                response.setHeader("Content-type", "text/html;charset=UTF-8");
                String data = "文件下载失败";
                OutputStream os = response.getOutputStream();
                os.write(data.getBytes(StandardCharsets.UTF_8));
                os.close();
                return;
            }
        } catch (Exception e) {
            log.error("文件名为空,下载失败!");
        }
        try (InputStream is = minioClient.getObject(GetObjectArgs.builder()
                .bucket(bucket)
                .object(fileName)
                .build());
             OutputStream os = response.getOutputStream()) {
            byte[] buf = new byte[1024];
            int length;
            response.reset();
            response.setHeader("Content-Disposition", "attachment;filename=" +
                    URLEncoder.encode(fileName.substring(fileName.lastIndexOf("/") + 1), "UTF-8"));
            response.setContentType("application/octet-stream");
            response.setCharacterEncoding("UTF-8");
            // 输出文件
            while ((length = is.read(buf)) > 0) {
                os.write(buf, 0, length);
            }
            // 判断:下载后是否同时删除minio上的存储文件
            if (BooleanUtils.isTrue(delete)) {
                minioClient.removeObject(RemoveObjectArgs.builder()
                        .bucket(bucket)
                        .object(fileName)
                        .build());
            }
        } catch (Exception ex) {
            response.setHeader("Content-type", "text/html;charset=UTF-8");
            String data = "文件下载失败";
            try {
                OutputStream ps = response.getOutputStream();
                ps.write(data.getBytes(StandardCharsets.UTF_8));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public List<ObjectItem> listObjects(String bucket, String prefix) {
        Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder()
                .bucket(bucket)
                .prefix(prefix)
                .recursive(true)
                .build());
        List<ObjectItem> objectItemList = new ArrayList<>();
        try {
            for (Result<Item> result : results) {
                Item item = result.get();
                ObjectItem objectItem = new ObjectItem();
                objectItem.setObjectName(item.objectName());
                objectItem.setSize(item.size());
                objectItemList.add(objectItem);
            }
        } catch (Exception e) {
            log.error("查看" + bucket + "中文件对象失败");
        }
        return objectItemList;
    }

    @Override
    public void removeFile(String bucket, String fileName) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder()
                    .bucket(bucket)
                    .object(fileName)
                    .build());
        } catch (Exception e) {
            log.error("删除[" + fileName.substring(fileName.lastIndexOf("/") + 1) + "]失败!");
        }
    }
}

其中upload上传文件方法中有一个FileUtils.extractUploadFileName()静态方法定义如下。

    /**
     * 提取上传文件名
     *
     * @param multipartFile 多部分文件
     * @return {@link String}
     */
    public static String extractUploadFileName(MultipartFile multipartFile) {
        String fileName = multipartFile.getOriginalFilename();
        if (fileName == null) {
            throw new RuntimeException("无法获取文件名称");
        }
        String prefix = UUID.randomUUID().toString();
        return getCurrentDatePath() + "/" + prefix + "-" + fileName;
    }

    /**
     * 获取当前日期路径
     *
     * @return {@link String}
     */
    private static String getCurrentDatePath() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
        return sdf.format(new Date());
    }
}

5.5 定义测试类

编写MinioController类对业务接口方法进行测试。

@RestController
@RequestMapping("/minio")
public class MinioController {
    @Resource
    private FileService fileService;

    @PostMapping("/upload")
    public void upload(MultipartFile file, String bucket) {
        fileService.upload(file, bucket);
    }

    @GetMapping("/download")
    public void download(String bucket, String fileName, boolean delete, HttpServletResponse response) {
        fileService.download(bucket, fileName, delete, response);
    }

    @GetMapping("/listObjects")
    public List<ObjectItem> listObjects(String bucket, String prefix) {
        return fileService.listObjects(bucket, prefix);
    }

    @PostMapping("/removeFile")
    public void removeFile(String bucket, String fileName) {
        fileService.removeFile(bucket, fileName);
    }
}

5.6 测试

5.6.1 上传

启动SpringBoot,将文件上传到刚才创建的bucket-test的Bucket中。
发送Post请求,上传文件,并填写要上传到的Bucket名称。
在这里插入图片描述
然后在MinIO的控制台就可以看到刚上传的文件了。
在这里插入图片描述
可以进行预览,也可以通过链接分享。
在这里插入图片描述
在上述文件中,设置的文件名称格式是:年/月/日/uuid-文件名.后缀。其中的斜杠/分割的路径会变成文件夹。

5.6.2 下载

发送Get请求或者Post请求均可(但是需要注意点击Send and Download按钮,否则只会显示二进制流数据,如果是Get请求,通过浏览器的http请求也可以下载到文件),填写bucket名称,fileName以及是否下载完就删除文件标志位delete,如果下载完要删除就设置成true,不删除就设置成false。
在这里插入图片描述
然后会提示你保存文件路径,并显示下载成功。
在这里插入图片描述
在桌面即可找到下载好的图片。
在这里插入图片描述
剩下的列出文件和删除文件接口也是输入入参的参数即可进行相应的操作。

事实上MinioClient类中提供了很多的操作数据的方法,可以自行去研究。并且整个MinioClient所提供的方法在最新的版本中均采用建造者模式来进行使用,将一个复杂对象的构建与表示分离开来,比起之前要方便不少。

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

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

相关文章

vivado中block design遇到的error总结

Error1.[BD 41-1356] Address block </processing_system7_0/S_AXI_HP0/HP0_DDR_LOWOCM> is not mapped into </axi_vdma_0/Data_MM2S>. Please use Address Editor to either map or exclude it. 修改方法. a、点击Address Editor. b、在Address Editor页面右击失…

【Ajax】了解Ajax与jQuery中的Ajax

一、了解Ajax什么是AjaxAjax 的全称是 Asynchronous Javascript And XML&#xff08;异步 JavaScript 和 XML&#xff09;。通俗的理解&#xff1a;在网页中利用 XMLHttpRequest 对象和服务器进行数据交互的方式&#xff0c;就是Ajax。2. 为什么要学Ajax之前所学的技术&#xf…

使用MQTT fx测试云服务器的 mosquitto 通讯

文章目录一.MQTT.fx介绍二.MQTT.fx安装教程三.使用MQTT.fx测试云服务器的 mosquitto 通讯一.MQTT.fx介绍 MQTT.fx是一款基于Eclipse Paho&#xff0c;使用Java语言编写的MQTT客户端工具。支持通过Topic订阅和发布消息&#xff0c;用来前期和物理云平台调试非常方便。 二.MQTT…

【数据结构——顺序表的实现】

前言&#xff1a; 在之前我们已经对复杂度进行的相关了解&#xff0c;因此现在我们将直接进入数据结构的顺序表的相关知识的学习。 目录1.线性表2.顺序表2.1概念及结构2.2 接口实现2.2.1.打印顺序表2.2.2初始化顺序表2.2.3.容量的检查2.2.4.销毁顺序表2.2.5.尾插操作2.2.6.尾删…

Ubuntu下的LGT8F328P MiniEVB Arduino开发和烧录环境

基于 LGT8F328P LQFP32 的 Arduino MiniEVB, 这个板型资料较少, 记录一下开发环境和烧录过程以及当中遇到的问题. 关于 LGT8F328P 芯片参数 8位RISC内核32K字节 Flash, 2K字节 SRAM最大支持32MHz工作频率 集成32MHz RC振荡器集成32KHz RC振荡器 SWD片上调试器工作电压: 1.8V…

C语言文件操作(3)

TIPS 1. 文件是不是二进制文件&#xff0c;不是后缀说了算&#xff0c;而是内容说了算 2. 文件的随机读写 文件的随机读写也就是说我指哪打哪 fseek() 人为调整指针指向的位置 1. 根据文件指针FILE*的当前位置和你给出的偏移量来让它这个文件指针呢定位到你想要的位置上…

Flutter 这一年:2022 亮点时刻

回看 2022&#xff0c;展望 Flutter Forward 2022 年&#xff0c;我们非常兴奋的看到 Flutter 社区持续发展壮大&#xff0c;也因此让更多人体验到了令人难以置信的体验。每天有超过 1000 款使用 Flutter 的新移动应用发布到 App Store 和 Google Play&#xff0c;Web 平台和桌…

实战打靶集锦-002-SolidState

**写在前面&#xff1a;**谨以此文纪念不完美的一次打靶经历。 目录1. 锁定主机与端口2. 服务枚举3. 服务探查3.1 Apache探查3.1.1 浏览器手工探查3.1.2 目录枚举3.2 JAMES探查3.2.1 搜索公共EXP3.2.2 EXP利用3.2.2.1 构建payload3.2.2.2 netcat构建反弹shell3.2.3 探查JAMES控…

三十一、Kubernetes中Service详解、实例第一篇

1、概述 在kubernetes中&#xff0c;pod是应用程序的载体&#xff0c;我们可以通过pod的ip来访问应用程序&#xff0c;但是pod的ip地址不是固定的&#xff0c;这也就意味着不方便直接采用pod的ip对服务进行访问。 为了解决这个问题&#xff0c;kubernetes提供了Service资源&…

NX二开ufun函数UF_MODL_ask_curve_points(获取曲线信息)

根据曲线tag&#xff0c;返回曲线相关信息&#xff1a;弦宽容、弧度、最大步长、点数组的点。 实例返回结果截图如下&#xff1a; 实例创建曲线截图如下&#xff1a; 1、函数结构 int UF_MODL_ask_curve_points &#xff08;tag_t curve_id&#xff0c; double ctol&#xf…

【SpringCloud19】SpringCloud Alibaba Sentinel实现熔断与限流

1.概述 官网 中文文档 1.1 是什么 一句话解释&#xff0c;之前我们讲解过的Hystrix 1.2 怎么下 下载网址 1.3 作用 1.4 如何使用 官网学习 服务使用中的各种问题&#xff1a; 服务雪崩服务降级服务熔断服务限流 2.安装Sentinel控制台 2.1 组成部分 核心库&#x…

Golang之实战篇(1)

"千篇一律&#xff0c;高手寂寞。几十不惑&#xff0c;全都白扯"上篇介绍了golang这门新的语言的一些语法。那么我们能用golang简单地写些什么代码出来呢&#xff1f;一、猜数字这个游戏的逻辑很简单。系统随机给你生成一个数&#xff0c;然后读取你猜的数字&#xf…

老杨说运维 | AIOps如何助力实现全面可观测性(上)

前言&#xff1a; 嗨&#xff0c;今天是大年三十&#xff0c;大家是不是已经在家坐享团圆之乐了&#xff1f;还是说在奔向团圆的路上呢&#xff1f;不论如何&#xff0c;小编先祝大家新年如意安康&#xff0c;平安顺遂~ 熟悉我们的朋友肯定都知道&#xff0c;关于《老杨说运维…

30.字符串处理函数

文章目录1.测字符串长度函数2.字符串拷贝函数1.strcpy函数2.strncpy函数3.字符串追加函数1.strcat函数2.strncat函数4.字符串比较函数1.strcmp函数2.strncmp函数5.字符查找函数1.strchr函数2.strrchr函数6.字符串匹配函数7.空间设定函数8.字符串转换数值9.字符串切割函数strtok…

【Java开发】Spring Cloud 04 :服务治理Nacos

本章节正式进入 Spring Cloud 环节了&#xff0c;首先介绍微服务架构中一个最重要的原理概念&#xff1a;服务治理&#xff0c;在概念讲解之后&#xff0c;讲解介绍 Nacos 服务注册中心的体系结构。1 服务治理1.1 服务治理介绍首先通过一个例子告诉你服务治理解决了什么问题。比…

GD32F4——外部中断

一、NVIC中断系统 Cortex-M4集成了嵌套式矢量型中断控制器&#xff08;Nested Vectored Interrupt Controller&#xff0c;NVIC&#xff09;来实现高效的异常和中断处理。 中断系统包含外部中断、定时器中断、DMA中断和串口中断等。 二、EXTI外部中断 EXTI&#xff08;中断…

go的基本语法介绍之变量的声明与初始化

1.常见基本数据类型 uint8&#xff1a;无符号8位整形&#xff0c;取值范围&#xff1a;0-255 uint16&#xff1a;无符号16位整形&#xff0c;取值范围&#xff1a;0-65535 uint32&#xff1a;无符号32位整形&#xff0c;取值范围&#xff1a;0-4294967295 uint64&#xff1…

opencv arm交叉编译与仿真验证详细流程

【关键内容】 1.将opencv编译为能在arm上运行的库 2.在没有板子的情况下&#xff0c;仿真验证opencv库 1.将opencv编译为能在arm上运行的库 1.在下方链接中选择某个版本 Releases - OpenCVhttps://opencv.org/releases/点击“Sources”即可开始下载&#xff0c;得到opencv-…

「数据结构、逻辑结构、物理结构」基本概念简析

前言 前言&#xff1a;简析数据结构、逻辑结构、物理结构。 文章目录前言一、数据结构1. 简介2. 数据3. 结构4. 分析5. 分类1&#xff09;线性结构&#xff08;线性表&#xff09;2&#xff09;树结构3&#xff09;图结构二、逻辑结构与物理结构1. 为什么要有逻辑结构和物理结构…

【leetcode合集】如何知道自己是否掌握了数组与链表?试试这几道题目吧!

目录 1.数组题目合集 1.1 leetcode.27 移除元素 1.2 leetcode.26 删除有序数组中的重复项 1.3 leetcode.88 合并两个有数数组 2.链表题目合集 2.1 leetcode.203 移除链表元素 2.2 leetcode.206 反转链表 2.3 leetcode.876 链表的中间结点 2.4 牛客 链表中倒数第k个结点…