SpringBoot整合Minio

1. Minio介绍

1.1 什么是Minio

Minio 是一个基于Apache License v2.0开源协议的对象存储服务。它可以运行在多种操作系统上,包括 Linux 和 Windows 等。

它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几kb到最大5TB不等。

Minio官网地址:MinIO | 用于AI的S3 & Kubernetes原生对象存储

Minio官方文档:技术文档

1.2 Minio的特点

  1. 简单易用: Minio的安装和配置非常简单,只需要下载并运行相应的二进制文件即可。它提供了一个Web UI,可以通过界面管理存储桶和对象。

  2. 可扩展性: Minio可以轻松地扩展到多个节点,以提供高可用性和容错能力。它支持多种部署模式,包括单节点、主从复制和集群等。

  3. 高可用性: Minio提供了多种机制来保证数据的可靠性和可用性,包括冗余备份、数据复制和故障转移等。

  4. 安全性: Minio提供了多种安全机制来保护数据的机密性和完整性,包括SSL/TLS加密、访问控制和数据加密等。

  5. 多语言支持: Minio支持多种编程语言,包括Java、Python、Ruby和Go等。

  6. 社区支持: Minio是一个开源项目,拥有庞大的社区支持和贡献者。它的源代码可以在GitHub上获得,并且有一个活跃的邮件列表和论坛。

  7. 对象存储: Minio的核心功能是对象存储。它允许用户上传和下载任意数量和大小的对象,并提供了多种API和SDK来访问这些对象。

  8. 块存储: Minio还支持块存储,允许用户上传和下载大型文件(例如图像或视频)。块存储是一种快速、高效的方式来处理大型文件。

  9. 文件存储: Minio还支持文件存储,允许用户上传和下载单个文件。文件存储是一种简单、快速的方式来处理小型文件。

2. Minio安装

2.1 Windows安装Minio

2.1.1 在D盘创建一个Minio的文件夹,并在里面建两个空的文件夹,一个是bin,一个是data

bin文件夹放下载的exe程序

data文件夹存储文件

2.1.2 下载Minio

下载地址:MinIO下载和安装 | 用于创建高性能对象存储的代码和下载内容

2.1.3 把下载好的 minio.exe 放到 2.1.1 创建的 bin 文件夹下
2.1.4 启动Minio

注意:不要双击运行!!!不要双击运行!!!不要双击运行!!!

在bin文件夹下,点击路径输入cmd,回车打开cmd窗口,或者通过命令定位到【D:\Minio\bin】文件夹中,输入下方命令,启动MinIO服务,不需要进行其他操作

复制代码
.\minio.exe server D:\Minio\data

注意:

启动后会显示minio的访问地址,默认的用户名和密码。

关闭窗口将停止minio服务器并结束该过程。

2.1.5 浏览器打开上面地址,输入用户名,密码,进行访问
2.1.6 固定端口访问
复制代码
.\minio.exe server D:\Minio\data --console-address :9001 --address :9000

客户端端口:--console-address :9001

服务器端口:--address :9000

2.1.7 修改用户名,密码

设置账号(至少3位):setx MINIO_ROOT_USER minioroot

设置密码(至少8位):setx MINIO_ROOT_PASSWORD minioroot

复制代码
setx MINIO_ROOT_USER minioroot

setx MINIO_ROOT_PASSWORD minioroot
2.18 创建 bat 启动文件

创建 runMinio.txt,复制下面的命令保存,修改文件名 runMinio.bat

复制代码
cmd /c "cd /d D:\Minio\bin&& .\minio.exe server D:\Minio\data

cmd /c "cd /d D:\Minio\bin&& .\minio.exe server D:\Minio\data --console-address :9001 --address :9000

下面的命令存后,双击运行,cmd窗口只是一闪而过,会加到服务里面

打开任务管理器,会发现minio服务是启动的,但是原来的cmd窗口已经被隐藏了

复制代码
@echo off
if "%1" == "h" goto begin
mshta vbscript:createobject("wscript.shell").run("""%~nx0"" h",0)(window.close)&&exit
:begin
REM
cmd /c "cd /d D:\Minio\bin&& .\minio.exe server D:\Minio\data

@echo off
if "%1" == "h" goto begin
mshta vbscript:createobject("wscript.shell").run("""%~nx0"" h",0)(window.close)&&exit
:begin
REM
cmd /c "cd /d D:\Minio\bin&& .\minio.exe server D:\Minio\data --console-address :9001 --address :9000

2.2 Linux安装Minio

2.2.1 在 home 路径下面创建 Minio 文件夹
2.2.2 下载
复制代码
wget https://dl.min.io/server/minio/release/linux-amd64/minio
2.2.3 添加执行权限给MinIO文件
复制代码
chmod +x minio
2.2.4 在 home/Minio下面创建 data 文件夹,做为文件存储路径
2.2.5 启动
复制代码
./minio server /home/Minio/data

./minio.exe server /home/Minio/data --console-address :9001 --address :9000

后台执行

复制代码
nohup /home/Minio/minio server /home/Minio/data --console-address :9001 --address :9000 > /dev/null 2>&1 &

2.3 创建 Bucket

2.3 创建 Access Key

3. Springboot接入Minio

3.1创建Springboot项目

3.2 pom文件添加依赖

复制代码
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.3.4</version>
</dependency>

3.3 application.yml添加配置

复制代码
#minio配置(下面四个都要替换成自己的)
minio:
  access-key: li5fasdfaeWFR344W2
  secret-key: p4VIZ23948ASDFJAjasdif2UFSDFc9b
  url: http://169.254.19.42:9000
  bucket-name: file

3.4 编写MinioConfig 配置类

复制代码
package com.minio.config;

import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {
    private String accessKey;

    private String secretKey;

    private String url;

    private String bucketName;

    @Bean
    public MinioClient minioClient(){
        return MinioClient.builder()
                .region("cn-north-1")
                .endpoint(url)
                .credentials(accessKey,secretKey)
                .build();
    }
}

3.5 编写MinioUtil工具类

复制代码
package com.minio.utils;

import com.minio.config.MinioConfig;
import io.minio.*;
import io.minio.http.Method;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;

import java.net.URLEncoder;
import java.util.concurrent.TimeUnit;

@Component
public class MinioUtil {

    @Autowired
    private MinioClient minioClient;

    @Autowired
    private MinioConfig configuration;

    /**
     * 判断bucket是否存在,不存在则创建
     */
    public boolean existBucket(String bucketName) {
        boolean exists;
        try {
            exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!exists) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
                exists = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            exists = false;
        }
        return exists;
    }

    /**
     * 删除bucket
     */
    public Boolean removeBucket(String bucketName) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 上传文件
     *
     * @param file     文件
     * @param fileName 文件名称
     */
    public void upload(MultipartFile file, String fileName) {
        // 使用putObject上传一个文件到存储桶中。
        try {
            InputStream inputStream = file.getInputStream();
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(configuration.getBucketName())
                    .object(fileName)
                    .stream(inputStream, file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取文件访问地址(有过期时间)
     *
     * @param fileName 文件名称
     * @param time     时间
     * @param timeUnit 时间单位
     */
    public String getExpireFileUrl(String fileName, int time, TimeUnit timeUnit) {
        try {
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(configuration.getBucketName())
                    .object(fileName)
                    .expiry(time, timeUnit).build());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取文件访问地址
     *
     * @param fileName 文件名称
     */
    public String getFileUrl(String fileName) {
        try {
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(configuration.getBucketName())
                    .object(fileName)
                    .build()
            );
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 下载文件
     *
     * @param fileName 文件名称
     */
    public void download(HttpServletResponse response, String fileName) {
        InputStream in = null;
        try {
            // 获取对象信息
            StatObjectResponse stat = minioClient.statObject(StatObjectArgs.builder().bucket(configuration.getBucketName()).object(fileName).build());
            response.setContentType(stat.contentType());
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            // 文件下载
            in = minioClient.getObject(GetObjectArgs.builder().bucket(configuration.getBucketName()).object(fileName).build());
            IOUtils.copy(in, response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 删除文件
     *
     * @param fileName 文件名称
     */
    public void delete(String fileName) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(configuration.getBucketName()).object(fileName).build());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

3.6 编写UploadController

复制代码
package com.minio.controller;

import com.minio.utils.MinioUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

/**
 * @author liyh
 */
@RestController
@RequestMapping("/api")
public class UploadController {

    @Autowired
    private MinioUtil minioUtil;

    /**
     * 上传文件
     */
    @PostMapping(value = "/upload")
    public String uploadReport(MultipartFile[] files) {
        for (MultipartFile file : files) {
            String fileName = file.getOriginalFilename();
            String rename = UUID.randomUUID().toString();
            minioUtil.upload(file, rename);
        }
        return "上传成功";
    }

    /**
     * 预览文件
     */
    @GetMapping("/preview")
    public String preview(String fileName) {
        return minioUtil.getFileUrl(fileName);
    }

    /**
     * 下载文件
     */
    @GetMapping("/download")
    public void download(String fileName, HttpServletResponse response) {
        minioUtil.download(response, fileName);
    }

    /**
     * 删除文件
     */
    @GetMapping("/delete")
    public String delete(String fileName) {
        minioUtil.delete(fileName);
        return "删除成功";
    }

}

4. 启动项目测试

4.1 上传文件

复制代码
http://127.0.0.1:8088/api/upload

4.2 预览文件

复制代码
http://127.0.0.1:8088/api/preview?fileName=

4.3 下载文件

复制代码
http://127.0.0.1:8088/api/download?fileName=

4.4 删除文件

复制代码
http://127.0.0.1:8088/api/delete?fileName=

5. 完整项目地址(Gitee

相关推荐
yyt3630458417 分钟前
spring单例bean线程安全问题讨论
java·spring
Sweet锦18 分钟前
SpringBoot 3.5 集成 InfluxDB 1.8
spring boot·时序数据库
我是大猴子27 分钟前
事务失效的几种情况以及是为什么(详解)
java·开发语言
wertyuytrewm1 小时前
Java面试——Java基础
java·jvm·面试
Java水解1 小时前
Spring Boot 消息队列与异步处理
spring boot·后端
czlczl200209251 小时前
RAG实现思路流程
java·jvm
带娃的IT创业者1 小时前
WeClaw_40_系统监控与日志体系:多层次日志架构与Trace追踪
java·开发语言·python·架构·系统监控·日志系统·链路追踪
Y001112361 小时前
JDBC原理
java·开发语言·数据库·jdbc
程序员侠客行2 小时前
Tomcat 从陌生到熟悉
java·tomcat·web
wertyuytrewm2 小时前
Java 异常|Java Exceptions
java·开发语言