【分布式文件存储系统Minio】2024.12保姆级教程

文章目录

1.介绍

1.分布式文件系统
2.基本概念

2.环境搭建

1.访问网址

http://ip:9090/

2.账号密码都是minioadmin
3.创建一个桶
4.Docker安装miniomc突破7天限制
1.拉取镜像
复制代码
docker pull minio/mc:RELEASE.2023-11-15T22-45-58Z.fips
2.运行容器
复制代码
docker run -it --entrypoint=/bin/sh minio/mc:RELEASE.2023-11-15T22-45-58Z.fips
3.进行配置
1.格式
复制代码
mc config host add <ALIAS> <YOUR-S3-ENDPOINT> <YOUR-ACCESS-KEY> <YOUR-SECRET-KEY>
2.具体配置
复制代码
mc config host add minio http://ip:9000 9i14IBbM2ysYVPDa52oK eXRpXcXcX5w4Tmy8HprUkemVi5zzrbpS4NksxxtU
4.查看桶
复制代码
mc ls minio
5.给桶开放权限
复制代码
mc anonymous set download minio/桶

3.搭建minio模块

1.创建一个oss模块
1.在sun-common下创建
2.引入minio依赖
1.sun-dependencies 锁定版本
复制代码
        <minio.version>8.2.0</minio.version>
        
        <!-- minio依赖 -->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>${minio.version}</version>
        </dependency>
2.sun-common-oss 引入依赖
复制代码
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <!-- 继承父模块的版本和通用依赖 -->
    <parent>
        <groupId>com.sunxiansheng</groupId>
        <artifactId>sun-common</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>

    <artifactId>sun-common-oss</artifactId>
    <!-- 子模块的version,如果不写就默认跟父模块的一样 -->
    <version>${children.version}</version>

    <dependencies>
        <!-- minio依赖 -->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
        </dependency>
        <!-- spring-boot-starter-web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-logging</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>

</project>
2.sun-common-oss 模块
1.概览
2.MinioConfig.java
复制代码
package com.sunxiansheng.oss.config;

import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * Description: minio配置管理
 * @Author sun
 * @Create 2024/5/31 9:22
 * @Version 1.0
 */
@Configuration
public class MinioConfig {

    /**
     * minioUrl
     */
    @Value("${minio.url}")
    private String url;

    /**
     * minio账户
     */
    @Value("${minio.accessKey}")
    private String accessKey;

    /**
     * minio密码
     */
    @Value("${minio.secretKey}")
    private String secretKey;

    /**
     * 构造minioClient
     */
    @Bean
    public MinioClient getMinioClient() {
        return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
    }

}
3.FileInfo.java
复制代码
package com.sunxiansheng.oss.entity;

import lombok.Data;

/**
 * FileInfo类用于存储文件的基本信息,包括文件名、是否为目录的标志以及文件的ETag。
 * 这个类可以在对象存储系统中用于描述文件的属性。
 * @Author sun
 * @Create 2024/5/31 9:47
 * @Version 1.0
 */
@Data
public class FileInfo {

    // 文件的名称
    private String fileName;

    // 指示该文件是否为目录的标志
    private Boolean directoryFlag;

    // 文件的ETag,用于标识文件的唯一性
    private String etag;

}
4.MinioUtil.java
复制代码
package com.sunxiansheng.oss.util;

import com.sunxiansheng.oss.entity.FileInfo;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * MinioUtil是一个用于与MinIO对象存储服务进行交互的工具类。
 * 提供了一系列方法用于管理存储桶和对象,包括创建桶、上传文件、下载文件、删除文件等操作。
 * @Author sun
 * @Create 2024/5/31 9:30
 * @Version 1.0
 */
@Component
public class MinioUtil {

    @Resource
    private MinioClient minioClient; // MinIO客户端实例,用于执行各种存储操作。

    /**
     * 创建存储桶。
     * 如果指定名称的存储桶不存在,则创建它。
     *
     * @param bucket 存储桶的名称
     * @throws Exception 如果创建存储桶时发生错误
     */
    public void createBucket(String bucket) throws Exception {
        boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
        if (!exists) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
        }
    }

    /**
     * 上传文件到指定存储桶。
     *
     * @param inputStream 文件输入流
     * @param bucket 存储桶的名称
     * @param objectName 对象名称,即文件在存储桶中的名称
     * @throws Exception 如果上传文件时发生错误
     */
    public void uploadFile(InputStream inputStream, String bucket, String objectName) throws Exception {
        minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName)
                .stream(inputStream, -1, 5242889L).build());
    }

    /**
     * 获取所有存储桶的名称列表。
     *
     * @return 存储桶名称的列表
     * @throws Exception 如果获取存储桶列表时发生错误
     */
    public List<String> getAllBucket() throws Exception {
        List<Bucket> buckets = minioClient.listBuckets();
        return buckets.stream().map(Bucket::name).collect(Collectors.toList());
    }

    /**
     * 获取指定存储桶中的所有文件信息。
     *
     * @param bucket 存储桶的名称
     * @return 文件信息列表,其中包含文件名、是否为目录标志和ETag
     * @throws Exception 如果获取文件列表时发生错误
     */
    public List<FileInfo> getAllFile(String bucket) throws Exception {
        Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(bucket).build());
        List<FileInfo> fileInfoList = new LinkedList<>();
        for (Result<Item> result : results) {
            FileInfo fileInfo = new FileInfo();
            Item item = result.get();
            fileInfo.setFileName(item.objectName());
            fileInfo.setDirectoryFlag(item.isDir());
            fileInfo.setEtag(item.etag());
            fileInfoList.add(fileInfo);
        }
        return fileInfoList;
    }

    /**
     * 从指定存储桶下载文件。
     *
     * @param bucket 存储桶的名称
     * @param objectName 对象名称,即文件在存储桶中的名称
     * @return 文件输入流,用于读取下载的文件内容
     * @throws Exception 如果下载文件时发生错误
     */
    public InputStream downLoad(String bucket, String objectName) throws Exception {
        return minioClient.getObject(
                GetObjectArgs.builder().bucket(bucket).object(objectName).build()
        );
    }

    /**
     * 删除指定存储桶。
     * 注意:存储桶必须为空才能被删除。
     *
     * @param bucket 存储桶的名称
     * @throws Exception 如果删除存储桶时发生错误
     */
    public void deleteBucket(String bucket) throws Exception {
        minioClient.removeBucket(
                RemoveBucketArgs.builder().bucket(bucket).build()
        );
    }

    /**
     * 删除指定存储桶中的文件。
     *
     * @param bucket 存储桶的名称
     * @param objectName 对象名称,即要删除的文件在存储桶中的名称
     * @throws Exception 如果删除文件时发生错误
     */
    public void deleteObject(String bucket, String objectName) throws Exception {
        minioClient.removeObject(
                RemoveObjectArgs.builder().bucket(bucket).object(objectName).build()
        );
    }

    /**
     * 获取文件的预览URL。
     * 该URL可以用于在浏览器中查看或下载文件。
     *
     * @param bucketName 存储桶的名称
     * @param objectName 对象名称,即文件在存储桶中的名称
     * @return 文件的预签名URL
     * @throws Exception 如果获取预签名URL时发生错误
     */
    public String getPreviewFileUrl(String bucketName, String objectName) throws Exception{
        GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
                .method(Method.GET)
                .bucket(bucketName).object(objectName).build();
        return minioClient.getPresignedObjectUrl(args);
    }
}
5.StorageAdapter.java
复制代码
package com.sunxiansheng.oss.adapter;

import com.sunxiansheng.oss.entity.FileInfo;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.List;

/**
 * StorageAdapter接口定义了与对象存储服务交互的方法。
 * 这些方法提供了基本的存储操作,如创建存储桶、上传和下载文件、获取文件信息等。
 * @Author sun
 * @Create 2024/5/31 10:03
 * @Version 1.0
 */
public interface StorageAdapter {

    /**
     * 创建存储桶。
     * 如果指定名称的存储桶不存在,则创建它。
     *
     * @param bucket 存储桶的名称
     */
    void createBucket(String bucket);

    /**
     * 上传文件到指定存储桶。
     *
     * @param uploadFile 要上传的文件
     * @param bucket 存储桶的名称
     * @param objectName 对象名称,即文件在存储桶中的名称
     */
    String uploadFile(MultipartFile uploadFile, String bucket, String objectName);

    /**
     * 获取所有存储桶的名称列表。
     *
     * @return 存储桶名称的列表
     */
    List<String> getAllBucket();

    /**
     * 获取指定存储桶中的所有文件信息。
     *
     * @param bucket 存储桶的名称
     * @return 文件信息列表,其中包含文件名、是否为目录标志和ETag
     */
    List<FileInfo> getAllFile(String bucket);

    /**
     * 从指定存储桶下载文件。
     *
     * @param bucket 存储桶的名称
     * @param objectName 对象名称,即文件在存储桶中的名称
     * @return 文件输入流,用于读取下载的文件内容
     */
    InputStream downLoad(String bucket, String objectName);

    /**
     * 删除指定存储桶。
     * 注意:存储桶必须为空才能被删除。
     *
     * @param bucket 存储桶的名称
     */
    void deleteBucket(String bucket);

    /**
     * 删除指定存储桶中的文件。
     *
     * @param bucket 存储桶的名称
     * @param objectName 对象名称,即要删除的文件在存储桶中的名称
     */
    void deleteObject(String bucket, String objectName);

    /**
     * 获取文件的访问URL。
     * 该URL可以用于在浏览器中查看或下载文件。
     * @param originalFilename 原始文件名
     * @param bucket 存储桶的名称
     * @param objectName 对象名称,即文件在存储桶中的名称
     * @return 文件的URL
     */
    public String getUrl(String originalFilename, String bucket, String objectName);
}
6.MinioStorageAdapter.java
复制代码
package com.sunxiansheng.oss.adapter;

import com.sunxiansheng.oss.entity.FileInfo;
import com.sunxiansheng.oss.util.MinioUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.List;

/**
 * MinioStorageAdapter类实现了StorageAdapter接口,使用MinioUtil类与MinIO对象存储服务进行交互。
 * 提供了一系列方法来管理存储桶和对象,包括创建桶、上传文件、下载文件、删除文件等操作。
 * @Author sun
 * @Create 2024/5/31 10:06
 * @Version 1.0
 */
@Component
public class MinioStorageAdapter implements StorageAdapter {

    @Resource
    private MinioUtil minioUtil; // 使用MinioUtil工具类来执行存储操作

    /**
     * MinIO服务的URL。
     * 该URL通常在配置文件中设置,用于构建文件访问的完整URL。
     */
    @Value("${minio.url}")
    private String url;

    /**
     * 创建存储桶。
     * 使用MinioUtil工具类创建存储桶。
     *
     * @param bucket 存储桶的名称
     */
    @Override
    @SneakyThrows
    public void createBucket(String bucket) {
        minioUtil.createBucket(bucket);
    }

    // ============================== 文件上传后的URL:url + 桶名 + 上传时的objectName ==============================
    /**
     * 上传文件到指定存储桶,并返回可访问的url
     * 使用提供的对象名称或文件的原始名称进行上传。
     *
     * @param uploadFile 要上传的文件
     * @param bucket 存储桶的名称
     * @param objectName 对象名称,表示完整的文件路径和名称
     */
    @Override
    @SneakyThrows
    public String uploadFile(MultipartFile uploadFile, String bucket, String objectName) {
        minioUtil.createBucket(bucket);
        String finalObjectName = generateObjectName(uploadFile.getOriginalFilename(), objectName);
        minioUtil.uploadFile(uploadFile.getInputStream(), bucket, finalObjectName);
        return getUrl(uploadFile.getOriginalFilename(), bucket, objectName);
    }

    /**
     * 自定义对象名的格式,上传时的对象名是什么格式,那么下载时的对象名也是什么格式
     * url的格式就是 url + 桶名 + 对象名
     *
     * @param originalFilename 原始文件名字
     * @param objectName 提供的对象名称
     * @return 最终用于存储的对象名称
     */
    private String generateObjectName(String originalFilename, String objectName) {
        // 如果对象名为空,则使用文件的原始名称作为对象名
        if (objectName == null) {
            return originalFilename;
        }
        // 如果对象名不为空,则对象名 + / + 文件名作为对象名
        return objectName + "/" + originalFilename;
    }

    /**
     * 获取文件的访问URL。
     * 该URL可以用于在浏览器中查看或下载文件。
     *
     * @param bucket 存储桶的名称
     * @param objectName 对象名称,即文件在存储桶中的名称
     * @return 文件的完整URL
     */
    @Override
    @SneakyThrows
    public String getUrl(String originalFilename, String bucket, String objectName) {
        // 首先生成对象名
        String finalObjectName = generateObjectName(originalFilename, objectName);
        // url的格式就是 url + 桶名 + 对象名
        return url + "/" + bucket + "/" + finalObjectName;
    }
    // ============================== 文件上传后的URL:url + 桶名 + 上传时的objectName ==============================

    /**
     * 获取所有存储桶的名称列表。
     *
     * @return 存储桶名称的列表
     */
    @Override
    @SneakyThrows
    public List<String> getAllBucket() {
        return minioUtil.getAllBucket();
    }

    /**
     * 获取指定存储桶中的所有文件信息。
     *
     * @param bucket 存储桶的名称
     * @return 文件信息列表,其中包含文件名、是否为目录标志和ETag
     */
    @Override
    @SneakyThrows
    public List<FileInfo> getAllFile(String bucket) {
        return minioUtil.getAllFile(bucket);
    }

    /**
     * 从指定存储桶下载文件。
     *
     * @param bucket 存储桶的名称
     * @param objectName 对象名称,即文件在存储桶中的名称
     * @return 文件输入流,用于读取下载的文件内容
     */
    @Override
    @SneakyThrows
    public InputStream downLoad(String bucket, String objectName) {
        return minioUtil.downLoad(bucket, objectName);
    }

    /**
     * 删除指定存储桶。
     * 注意:存储桶必须为空才能被删除。
     *
     * @param bucket 存储桶的名称
     */
    @Override
    @SneakyThrows
    public void deleteBucket(String bucket) {
        minioUtil.deleteBucket(bucket);
    }

    /**
     * 删除指定存储桶中的文件。
     *
     * @param bucket 存储桶的名称
     * @param objectName 对象名称,即要删除的文件在存储桶中的名称
     */
    @Override
    @SneakyThrows
    public void deleteObject(String bucket, String objectName) {
        minioUtil.deleteObject(bucket, objectName);
    }

}
3.sun-demo操作minio
1.引入sun-common-oss
复制代码
        <!-- 引入sun-common-oss -->
        <dependency>
            <groupId>com.sunxiansheng</groupId>
            <artifactId>sun-common-oss</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
2.application.yml 配置minio参数
复制代码
# minio配置
minio:
  url: http://ip:9000
  accessKey: minioadmin
  secretKey: minioadmin
3.暴露接口 MinioController.java
复制代码
package com.sunxiansheng.user.controller;

import com.sunxiansheng.oss.adapter.StorageAdapter;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

/**
 * Description:
 * @Author sun
 * @Create 2024/8/2 16:25
 * @Version 1.0
 */
@RestController
public class MinioController {

    @Resource
    private StorageAdapter storageAdapter;

    /**
     * 上传文件并返回url
     */
    @RequestMapping("/upload")
    public String upload(MultipartFile uploadFile, String bucket, String objectName) throws Exception {
        return storageAdapter.uploadFile(uploadFile, bucket, objectName);
    }

}
4.测试
相关推荐
国科安芯1 小时前
ASL706S:让 MCU 不再“失忆跑飞“的守护芯片
分布式·单片机·嵌入式硬件·安全·fpga开发·架构
阿无,3 小时前
RabbitMQ面试题
分布式·rabbitmq
盛世宏博智慧档案5 小时前
全国100个分布式机房环境温湿度智能监测系统建设方案
分布式·机房·温湿度
六bring个六6 小时前
分布式设备连接对端失败问题分析
分布式·分布式软总线
天涯明月199312 小时前
ray深度研究报告
大数据·人工智能·分布式·ray
Rain的Java大神之路1 天前
介绍一下分布式事务
java·分布式·后端·spring·spring cloud·架构·springcloud
大菠萝爱上小西瓜1 天前
【大数据实战】Spark 2.2.2 完全分布式集群搭建
大数据·分布式·spark
肠畔码农1 天前
深度解析 RocketMQ 消费端限流与重平衡(Rebalance):分布式队列分配与流控防雪崩本质
分布式·rocketmq
海兰1 天前
【 Kafka进阶3】Apache Kafka 分布式事件流平台:架构原理与微服务解耦机制简要分析
分布式·架构·kafka
麻瓜记录Jackson2 天前
深入剖析 ZooKeeper 分布式 互斥锁:Curator 之 InterProcessMutex 源码全解(附图解)
java·spring boot·分布式·后端·zookeeper·java-zookeeper