文章目录

  • 前言
  • 一、前提简介
  • 1、什么是对象存储?
  • 2、什么是MinIO?
  • 2.1 minIO特性
  • 二、安装使用MinIO
  • 三、简单在springboot中使用
  • 导入依赖
  • 在yam或者yaml文件中配置
  • 上代码



前言

使用minio进行文件上传


一、前提简介

1、什么是对象存储?

阿里云OSS解释:
对象存储服务OSS(Object Storage Service)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。

对象存储最大的优势就在于它可以存储大容量的非结构化数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等。对于大多数的企业来说,这可以说是最为理想的存储媒介了。

对于业务已在公有云上的企业来说,使用公有云提供的 OSS 服务,可以很好的节省存储的成本,且一般都提供易接入的 SDK,以阿里云的OSS 服务为例,在存储介质的上层封装可标注的 RESTful API 接口,使用起来十分方便。

但是对于一些没有选择业务上云或者想要下云的企业来说,要使用公有云的 OSS,在公网带宽方面就需要有一定的投入,毕竟需要通过公网传输,带宽太小,传输速度就会慢,且在传输过程中数据的安全性和完整性也有损失的风险,走专线的费用又十分昂贵,不实在。

这种情况下,MinIO 就是一个不错的选择,麻雀虽小,五脏俱全,企业可以以此快速构建自己内部的对象存储服务。(可以简单的认为MinIO就是一个远程的硬盘(存储数据))

2、什么是MinIO?

Minio 是个基于 Golang 编写的开源对象存储套件,基于Apache License v2.0开源协议,虽然轻量,却拥有着不错的性能。它兼容亚马逊S3云存储服务接口。可以很简单的和其他应用结合使用,例如 NodeJS、Redis、MySQL等。

它由桶(bucket,对应Windows下的文件夹),组成目录结构,桶中直接存放对象(Object,对应Windwos下的文件),桶中不能再创建通,但是要能创建文件夹 。

2.1 minIO特性

1. 高性能:
作为一款高性能存储,在标准硬件条件下,其读写速率分别可以达到 55Gb/s 和 35Gb/s。并而 MinIO 支持一个对象文件可以是任意大小,从几kb到最大5T不等。
2.可扩展:
不同MinIO集群可以组成联邦,并形成一个全局的命名空间,并且支持跨越多个数据中心。
3.云原生:
容器化、基于K8S的编排、多租户支持。

4.Amazon S3兼容:
使用 Amazon S3 v2 / v4 API。可以使用Minio SDK,Minio Client,AWS SDK 和 AWS CLI 访问Minio服务器。

5.可对接多种后端存储:
除了Minio自己的文件系统,还支持 DAS、 JBODs、NAS、Google云存储和 Azure Blob存储。

6.SDK支持:

GO SDK: https://github.com/minio/minio-go

JavaSDK: https://github.com/minio/minio-java

PythonSDK: https://github.com/minio/minio-py

7.Lambda计算:
Minio服务器通过其兼容AWS SNS / SQS的事件通知服务触发Lambda功能。支持的目标是消息队列,如Kafka,NATS,AMQP,MQTT,Webhooks以及Elasticsearch,Redis,Postgres和MySQL等数据库。

8.图形化界面
有操作页面。

9.功能简单:
不容易出错,快速启动。

10.支持纠删码:
MinIO使用纠删码、Checksum来防止硬件错误和静默数据污染。在最高冗余度配置下,即使丢失1/2的磁盘也能恢复数据。

二、安装使用MinIO

1、下载minio(官网下载:https://docs.min.io/)

2、将MinIO.exe 拷贝到自己的目录下去,并创建一个data目录

OSS对象存储nestjs 对象存储oss的应用场景_上传

3、通过命令行启动Minio : minio server ./dta

4、启动完成后,可以看到访问的路径http://127.0.0.1:9000 (浏览器中打开)

。。。(在页面中创建桶就可以了)

三、简单在springboot中使用

导入依赖

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

在yam或者yaml文件中配置

# Miniio配置
minio:
  endpoint: 127.0.0.1     	#ip地址
  port: 9000				#  端口号
  accessKey: minioadmin     #  账号
  secretKey: minioadmin		#  密码
  secure: false				#如果是true,则用的是https而不是http,默认值是true
  bucketName: "name"   # 桶的名字
  configDir: "/data/excel"  #保存到本地的路径

上代码

/**
     * 文件上传至Minio
     * 使用try catch finally进行上传
     * finally里进行资源的回收
     */
    @Override
    public AjaxResult upload(MultipartFile file) {
        InputStream inputStream = null;
        //创建Minio的连接对象
        MinioClient minioClient = getClient();
        //桶对象
        String bucketName = minioConfig.getBucketName();
        try {
            inputStream = file.getInputStream();
            //基于官网的内容,判断文件存储的桶是否存在 如果桶不存在就创建桶
            boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().build());
            if (exists) {
                System.out.println("该桶已经存在");
            } else {
                minioClient.makeBucket(MakeBucketArgs.builder().build());
            }
            /**
             * ================================操作文件================================
             * 思路:我们上传的文件是:文件.pdf
             * 那么我们应该上传到配置的bucket内 我们配置的bucketName是name
             * 那么我们存在桶里的文件应该是什么样的 也叫“文件.pdf”吗?
             * 应该按照上传的年月日进行区分
             * 举例:2021-05-05日进行上传的
             * 那么存在桶里的路径应该是
             * name/2021/05/05/这个目录下
             * 而对于同一个文件,存在重名问题,所以我们应该利用UUID生成一个新的文件名,并拼接上 .pdf 作为文件后缀
             * 那么完整的路径就是 name/2021/05/05/uuid.pdf
             *
             * 如果上述思路你无法理解,那么就直接存放在桶内生成uuid+.pdf即可
             * 即:name/uuid.pdf
             */
            //操作文件
            String fileName = file.getOriginalFilename();
            String objectName = new SimpleDateFormat("yyyy/MM/dd/").format(new Date()) + UUID.randomUUID().toString().replaceAll("-", "")
                    + fileName.substring(fileName.lastIndexOf("."));
            PutObjectArgs objectArgs = PutObjectArgs.builder().object(objectName)
                    .bucket(bucketName)
                    .contentType(file.getContentType())
                    .stream(file.getInputStream(), file.getSize(), -1).build();
            minioClient.putObject(objectArgs);
            //封装访问的url给前端
            AjaxResult ajax = AjaxResult.success();
            ajax.put("fileName", "/" + bucketName + "/" + objectName);
            //url需要进行截取
            ajax.put("url", minioConfig.getEndpoint() + ":" + minioConfig.getPort() + "/" + minioConfig.getBucketName() + "/" + fileName);
            /**
             * 构建返回结果集
             */

            /**
             * 封装需要的数据进行返回
             */
            return ajax;
        } catch (Exception e) {
            e.printStackTrace();
            return AjaxResult.error("上传失败");
        } finally {
            //防止内存泄漏
            if (inputStream != null) {
                try {
                    inputStream.close(); // 关闭流
                } catch (IOException e) {
                    log.debug("inputStream close IOException:" + e.getMessage());
                }
            }
        }
    }


//这个方法里面的属性用了一个配置文件实体类(minioConfig)(也就是一些minio的连接属性)
//属性自己看文档定义
    /**
     * 免费提供一个获取Minio连接的方法
     * 获取Minio连接
     * @return
     */
    private MinioClient getClient() {
        MinioClient minioClient =
                MinioClient.builder()
                        .endpoint("http://" + minioConfig.getEndpoint() + ":" + minioConfig.getPort())
                        .credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
                        .build();
        return minioClient;
    }