【分布式云储存】Springboot微服务接入MinIO实现文件服务

这篇具有很好参考价值的文章主要介绍了【分布式云储存】Springboot微服务接入MinIO实现文件服务。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

上篇博客我们介绍了分布式云存储MinIO作业环境的搭建,以及分布式云储存MinIO在实际的文件服务中的优势。那么,今天我们就小试牛刀来将MinIO接入我们的微服务项目,实现一个分布式的文件服务器。

技术回顾

MinIO 提供高性能、与S3 兼容的对象存储系统,让你自己能够构建自己的私有云储存服务。
MinIO原生支持 Kubernetes,它可用于每个独立的公共云、每个 Kubernetes 发行版、私有云和边缘的对象存储套件。
MinIO是软件定义的,不需要购买其他任何硬件,在 GNU AGPL v3 下是 100% 开源的。

准备工作

申请accessKey\secretKey

MinIO控制台申请accessKey\secretKey
http://your_hostname:18001~18004/login minio/minio123
【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO

创建数据存储桶

创建数据存储桶
【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO

点击创建的桶我们进行访问策略配置
【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO
【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO

访问策略有private\custom\public
public 公共的桶,任何人都可以访问资源,直接映射为静态资源,可直接提供预览和下载
custom 自定义桶,用户根据自身需求定义访问规则
private 私有的桶,需要授权才能访问

根据一般的生产需求,我们定义一个private,一个custom桶。private保存私有资源,custom保存公共资源并禁止目录访问。
【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO

private 规则:
【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO

custom 规则:
【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "*"
                ]
            },
            "Action": [
                "s3:GetBucketLocation",
                "s3:ListBucketMultipartUploads"
            ],
            "Resource": [
                "arn:aws:s3:::sacpublic"
            ]
        },
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "*"
                ]
            },
            "Action": [
                "s3:AbortMultipartUpload",
                "s3:DeleteObject",
                "s3:GetObject",
                "s3:ListMultipartUploadParts",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::sacpublic/*"
            ]
        }
    ]
}

公共资源直接访问测试

私有资源代码博文最后测试
公共资源直接访问测试:
【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO
【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO

接入springboot实现文件服务

依赖引入

maven引入依赖

<!--minio-->
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.2.0</version>
</dependency>
<!--minio-->

配置文件

配置文件

minio.url = https://10.10.22.91:9100
minio.accessKey = fUIXbkBZ9UQTHOOZXNGW
minio.secretKey = sy1RAgItAOk9pk1gE7FbrPYzsZI87CfpGkuoY0KW
minio.buckets.public = sacpublic
minio.buckets.private = sacprivate

注意:接口调用minio url 为nginx映射出来的9000端口
http://your_hostname:9000

MinIO配置

MinIO配置

/**
 * MinioConfig
 * @author senfel
 * @version 1.0
 * @date 2023/9/14 11:37
 */
@Configuration
@ConditionalOnProperty(name = "oss.file.service", havingValue = "minio", matchIfMissing = true)
public class MinioConfig {

    @Value("${minio.url}")
    private String minioUrl;
    @Value("${minio.accessKey}")
    private String accessKey;
    @Value("${minio.secretKey}")
    private String secretKey;

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

MinIO工具类

MinIO工具类

/**
 * MinioUtil
 * @author senfel
 * @version 1.0
 * @date 2023/9/14 10:26
 */
@Component
@ConditionalOnProperty(name = "oss.file.service", havingValue = "minio", matchIfMissing = true)
public class MinioUtil {

    @Resource
    private MinioClient minioClient;

    /**
     * 创建一个桶
     */
    public void createBucket(String bucket) throws Exception {
        boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucket).build());
        if (!found) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucket).build());
        }
    }

    /**
     * 上传一个文件
     */
    public ObjectWriteResponse uploadFile(InputStream stream, String bucket, String objectName) throws Exception {
        String prefix = objectName.substring(objectName.lastIndexOf(".") + 1);
        //静态资源预览解决方案
        //String contentType = ViewContentType.getContentType(prefix);
        ObjectWriteResponse objectWriteResponse = minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName)
                .contentType(contentType)
                .stream(stream, -1, 10485760).build());
        return objectWriteResponse;
    }

    /**
     * 列出所有的桶
     */
    public List<String> listBuckets() throws Exception {
        List<Bucket> list = minioClient.listBuckets();
        List<String> names = new ArrayList<>();
        list.forEach(b -> {
            names.add(b.name());
        });
        return names;
    }

    /**
     * 下载一个文件
     */
    public InputStream download(String bucket, String objectName) throws Exception {
        InputStream stream = minioClient.getObject(
                GetObjectArgs.builder().bucket(bucket).object(objectName).build());
        return stream;
    }

    /**
     * 删除一个桶
     */
    public void deleteBucket(String bucket) throws Exception {
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucket).build());
    }

    /**
     * 删除一个对象
     */
    public void deleteObject(String bucket, String objectName) throws Exception {
        minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucket).object(objectName).build());
    }

    /**
     * 复制文件
     *
     * @Param: [sourceBucket, sourceObject, targetBucket, targetObject]
     * @return: void
     * @Date: 2021/11/15
     */
    public void copyObject(String sourceBucket, String sourceObject, String targetBucket, String targetObject) throws Exception {
        this.createBucket(targetBucket);
        minioClient.copyObject(CopyObjectArgs.builder().bucket(targetBucket).object(targetObject)
                .source(CopySource.builder().bucket(sourceBucket).object(sourceObject).build()).build());
    }

    /**
     * 获取文件信息
     *
     * @Param: [bucket, objectName]
     * @return: java.lang.String
     */
    public String getObjectInfo(String bucket, String objectName) throws Exception {
        return minioClient.statObject(StatObjectArgs.builder().bucket(bucket).object(objectName).build()).toString();
    }

    /**
     * 生成一个给HTTP GET请求用的presigned URL。浏览器/移动端的客户端可以用这个URL进行下载,即使其所在的存储桶是私有的。
     * @Param: [bucketName, objectName, expires]
     * @return: java.lang.String
     */
    public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) throws Exception {
        GetPresignedObjectUrlArgs build = GetPresignedObjectUrlArgs
                .builder().bucket(bucketName).object(objectName).expiry(expires).method(Method.GET).build();
        return minioClient.getPresignedObjectUrl(build);
    }

}

OkHttpSSLSocketClient兼容ssl

对于改解决方案一般生产环境都有固定的域名和匹配的ssl证书,如果也不用https我们代码则不用兼容ssl。但是如果我们配置了不可信任的ssl,这里我们则需要进行ssl兼容方案。

/**
 * MinioConfig
 * @author senfel
 * @version 1.0
 * @date 2023/9/14 11:37
 */
@Configuration
@ConditionalOnProperty(name = "oss.file.service", havingValue = "minio", matchIfMissing = true)
public class MinioConfig {

    @Value("${minio.url}")
    private String minioUrl;
    @Value("${minio.accessKey}")
    private String accessKey;
    @Value("${minio.secretKey}")
    private String secretKey;

   @Bean
    public MinioClient getMinioClient() {
        OkHttpClient okHttpClient = new OkHttpClient.Builder()
                .sslSocketFactory(OkHttpSSLSocketClient.getSSLSocketFactory(),OkHttpSSLSocketClient.getX509TrustManager()) // //通过sslSocketFactory方法设置https证书
                .hostnameVerifier(OkHttpSSLSocketClient.getHostnameVerifier())
                .build();
        return MinioClient.builder().endpoint(minioUrl).httpClient(okHttpClient)
                .credentials(accessKey, secretKey).build();
    }
    
}
/**
 * OkHttpSSLSocketClient
 * @author senfel
 * @version 1.0
 * @date 2023/9/15 10:07
 */
public class OkHttpSSLSocketClient{
    //获取SSLSocketFactory
    public static SSLSocketFactory getSSLSocketFactory() {
        try {
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, getTrustManager(), new SecureRandom());
            return sslContext.getSocketFactory();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    //获取TrustManager
    private static TrustManager[] getTrustManager() {
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(X509Certificate[] chain, String authType) {
                    }

                    @Override
                    public void checkServerTrusted(X509Certificate[] chain, String authType) {
                    }

                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return new X509Certificate[]{};
                    }
                }
        };
        return trustAllCerts;
    }

    //获取HostnameVerifier,验证主机名
    public static HostnameVerifier getHostnameVerifier() {
        HostnameVerifier hostnameVerifier = (s, sslSession) -> true;
        return hostnameVerifier;
    }
    //X509TrustManager:证书信任器管理类
    public static X509TrustManager getX509TrustManager() {
        X509TrustManager x509TrustManager = new X509TrustManager() {
            //检查客户端的证书是否可信
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) {

            }
            //检查服务器端的证书是否可信
            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) {

            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        };
        return x509TrustManager;
    }
}

静态资源预览解决方案

由于我们使用API上传,minio不能区分我们资源的类型,如果资源类型不对则不能正确提供预览功能,都直接变成为访问资源链接就下载了。

所以,在实际的项目集成中我们在上传资源前需要将资源类型写入请求中,方便minio解析并提供预览和下载功能。

/**
 * 上传一个文件
 */
public ObjectWriteResponse uploadFile(InputStream stream, String bucket, String objectName) throws Exception {
    String prefix = objectName.substring(objectName.lastIndexOf(".") + 1);
    //静态资源预览解决方案
    String contentType = ViewContentType.getContentType(prefix);
    ObjectWriteResponse objectWriteResponse = minioClient.putObject(PutObjectArgs.builder().bucket(bucket).object(objectName)
            .contentType(contentType)
            .stream(stream, -1, 10485760).build());
    return objectWriteResponse;
}
/**
 * ViewContentType
 * @author senfel
 * @version 1.0
 * @date 2023/9/14 17:27
 */
public enum ViewContentType {
    DEFAULT("default","application/octet-stream"),
    JPG("jpg", "image/jpeg"),
    TIFF("tiff", "image/tiff"),
    GIF("gif", "image/gif"),
    JFIF("jfif", "image/jpeg"),
    PNG("png", "image/png"),
    TIF("tif", "image/tiff"),
    ICO("ico", "image/x-icon"),
    JPEG("jpeg", "image/jpeg"),
    WBMP("wbmp", "image/vnd.wap.wbmp"),
    FAX("fax", "image/fax"),
    NET("net", "image/pnetvue"),
    JPE("jpe", "image/jpeg"),
    RP("rp", "image/vnd.rn-realpix");
    private String prefix;
    private String type;
    public static String getContentType(String prefix){
        if(StringUtils.isEmpty(prefix)){
            return DEFAULT.getType();
        }
        prefix = prefix.substring(prefix.lastIndexOf(".") + 1);
        for (ViewContentType value : ViewContentType.values()) {
            if(prefix.equalsIgnoreCase(value.getPrefix())){
                return value.getType();
            }
        }
        return DEFAULT.getType();
    }

    ViewContentType(String prefix, String type) {
        this.prefix = prefix;
        this.type = type;
    }

    public String getPrefix() {
        return prefix;
    }

    public String getType() {
        return type;
    }
}




资源上传预览测试

MinIO对于图片等资源可以直接预览,对于excel文档等直接提供下载功能

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class CodeDbInfoServiceTests  {

    @Resource
    @Lazy
    private MinioUtil minioUtil;


    /**
     * upload
     * @author senfel
     * @date 2023/9/27 10:00
     * @return void
     */
    @Test
    public void upload() throws Exception {
        FileInputStream fileInputStream = new FileInputStream("C:/Users/dev/Desktop/minio.png");
        ObjectWriteResponse sacprivate = minioUtil.uploadFile(fileInputStream, "sacprivate", "test/minio.png");
        System.err.println(sacprivate.bucket());
    }

    /**
     * 获取私库连接
     * @author senfel
     * @date 2023/9/27 10:01
     * @return void
     */
    @Test
    public void getPrivateUrl() throws Exception{
        String url = minioUtil.getPresignedObjectUrl("sacprivate", "test/minio.png", 60);
        System.err.println(url);
    }
}

测试结果

图片成功上传
【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO

私库直接预览访问失败
【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO

获取私库链接过期时间为60s
【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO

访问成功
【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO

60s后再次访问该链接,提示链接已经过期
【分布式云储存】Springboot微服务接入MinIO实现文件服务,云存储,开发工具,Spring,分布式,spring boot,微服务,文件服务,MinIO

至此minio接入并测试完成,对于公开桶的资源直接可任意访问不用获取有效期链接。

写在最后
Springboot微服务接入MinIO实现文件服务较为简单,我们只要按照官方文档引入依赖调用即可。值得注意的是我们根据需求选择接入ssl兼容方案和静态资源预览功能。当然,minio的private\custom\public可以完全实现我们各种需求,可以完全替代市场上付费和笨重的分布式服务。文章来源地址https://www.toymoban.com/news/detail-729506.html

到了这里,关于【分布式云储存】Springboot微服务接入MinIO实现文件服务的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 分布式文件服务器——Windows环境MinIO的三种部署模式

    上节简单聊到MinIO:分布式文件存储服务——初识MinIO-CSDN博客,但没具化,本节开始展开在Windows环境下 MinIO的三种部署模式: 单机单节点、单机纠删码、集群模式 。 部署的几种模式简要概括 所谓单机单节点模式:即MinIO服务只部署到一台机器上,且只挂载一块磁盘(目录)

    2024年02月07日
    浏览(69)
  • 【Spring Cloud】新闻头条微服务项目:分布式文件系统MinIO实现文章页面存取

      个人简介:  📦个人主页:赵四司机 🏆学习方向:JAVA后端开发  📣种一棵树最好的时间是十年前,其次是现在! ⏰往期文章:SpringBoot项目整合微信支付 🧡喜欢的话麻烦点点关注喔,你们的支持是我的最大动力。 前言: 最近在做一个基于SpringCloud+Springboot+Docker的新闻头

    2023年04月08日
    浏览(59)
  • 分布式文档储存————elasticsearch学习笔记(四)

    之前有提到一个文档至少被储存在一个主分片中,副本分片可以有多个,但是主分片至少有一个。 因此,例如一个集群被设置有3个主分片,为了保证文档被均匀的存储在这些主分片,es会根据routing(可能是文档的id或自己设置),通过一个hash算法将文档分配到一个主分片中

    2023年04月22日
    浏览(43)
  • 【分布式技术专题】「OSS中间件系列」Minio的文件服务的存储模型及整合Java客户端访问的实战指南

    Minio的元数据 数据存储 MinIO对象存储系统没有元数据数据库,所有的操作都是对象级别的粒度的,这种做法的优势是: 个别对象的失效,不会溢出为更大级别的系统失效。 便于实现\\\"强一致性\\\"这个特性。此特性对于机器学习与大数据处理非常重要。 数据管理 元数据与数据一起

    2024年02月11日
    浏览(59)
  • minio分布式文件存储

    基本介绍 什么是  MinIO         MinIO 是一款基于 Go 语言的高性能、可扩展、云原生支持、操作简单、开源的分布式对象存储产品。基于 Apache License v2.0 开源协议,虽然轻量,却拥有着不错的性能。它兼容亚马逊S3云存储服务接口。可以很简单的和其他应用结合使用,例如

    2024年02月08日
    浏览(48)
  • 分布式文件系统使用——MinIO

    1.1 概念 常见的文件系统:FAT16/FAT32、NTFS、HFS、UFS、APFS、XFS、Ext4等 。 现在有个问题,一此短视频平台拥有大量的视频、图片,这些视频文件、图片文件该如何存储呢?如何存储可以满足互联网上海量用户的浏览。 分布式文件系统 就是海量用户查阅海量文件的方案。 通过概

    2024年02月12日
    浏览(42)
  • 分布式文件存储MinIO-监控

    MinIO自身提供了关于集群状态和操作的相关的Prometheus SQL指标与支持Prometheus数据模型的监控指标收集工具进行搭配使用,无论是主机部署亦或是云上部署都可以进行集成。官方选定的第三方监控软件为Prometheus和InfluxDB,使用者可以根据各自公司对于监控设施的建设进行选择。

    2024年02月11日
    浏览(54)
  • Docker搭建MinIo分布式系统

    文件系统是负责管理和存储文件的系统软件,操作系统通过文件系统提供的接口去存取文件,用户通过操作系统访问磁盘上的文件。 下图指示了文件系统所处的位置: 通过概念可以简单理解为:一个计算机无法存储海量的文件,通过网络将若干计算机组织起来共同去存储海

    2024年02月04日
    浏览(47)
  • minio 分布式文件系统主从复制

    1. 在slave节点下载mc客户端工具 下载 2. 移动或复制mc文件到/usr/local/bin/文件夹 3. 赋值权限给 mc 文件 4. 查看mc客户端版本,看是否可用 5. 在slave服务器上配置minio_slave和minio_master,用于添加对master上minio的访问权限。 6. 查看当前节点服务 7. 复制主节点数据到子节点

    2024年02月13日
    浏览(44)
  • 聊聊分布式架构08——SpringBoot开启微服务时代

    目录 微服务架构时代 快速入门 入门详解 SpringBoot的自动配置 石器时代:XML配置bean 青铜时代:SpringConfig 铁器时代:AutoConfigurationImportSelector 手写简单Starter SpringApplication启动原理 微服务架构时代 Spring Boot的出现与微服务架构有关,它是Spring Framework的一部分,旨在简化开发独

    2024年02月06日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包