CentOS7安装MiniO

1、MiniO介绍

FastDFS部署麻烦还不好修改,MiniO基于Go,安装简单,其他都可以通过可视化进行操作。

官网:https://www.minio.org.cn/
文档:https://www.minio.org.cn/docs/cn/minio/linux/index.html

2、安装

安装使用的是CentOS7.9,使用单击部署,不使用k8s/docker

2.0、必要条件

  • 准备好一个文件夹用来存储文件
  • 准备好两个端口,一个用于MiniO服务,一共用于可视化界面服务
    firewall-cmd --add-port=xxxx/tcp --per
    

2.1、安装MiniO服务

MiniO提供Binary、RPM、DEB三种安装方式。此处推荐使用RPM或DEB安装,它会自动帮助你配置systemctl。但实际选择对应的系统安装方式还是二进制都是一样的。
文档存在过旧,可以访问 https://www.minio.org.cn/download.shtml#/linux 来获取最新的安装方式。

  1. Binary
    wget https://dl.minio.org.cn/server/minio/release/linux-amd64/minio;
    chmod +x minio;
    
  2. RPM(RHEL)就是红帽,CentOS就用这个
    dnf install https://dl.minio.org.cn/server/minio/release/linux-amd64/minio-20230518000536.0.0.x86_64.rpm;
    
  3. DEB(Ubuntu/Debian)
    wget https://dl.minio.org.cn/server/minio/release/linux-amd64/minio_20230518000536.0.0_amd64.deb;
    dpkg -i minio_20230518000536.0.0_amd64.deb;
    

2.2、启动MiniO服务

MINIO_ROOT_USER=admin MINIO_ROOT_PASSWORD=password minio server /home/ --address :9000 --console-address :9090
  • MINIO_ROOT_USER:用于可视化操作登录时管理员的账号。[可选]
  • MINIO_ROOT_PASSWORD:用于可视化操作登录时管理员的密码。[可选]
  • minio server <dataPath>: 服务启动。[必选]
    • dataPath: 文件存储路径,该路径可以为节点的网址/真实的路径。[必填]
  • --address :<port>: 文件服务的端口号,默认为9000。[可选]
  • --console-address :<port>:可视化界面的端口号,默认为随机。[可选]

2.3、进入服务

输入对应的服务路径 IP:PORT 即可进入可视化界面

2.4、添加配置文件

这里是固定管理员账户

# 进入配置文件
vim /tec/profile
#添加内容
export MINIO_ROOT_USER=root
export MINIO_ROOT_PASSWORD=12345678
#保存并重新加在
source /etc/profile
# 此时启动:minio server /home/ --address :9000 --console-address :9090

3、第三方软件调用MiniO

依然可以在 https://www.minio.org.cn/download.shtml#/linux 获取对应的SDK方式。参考文档参考:https://min.io/docs/minio/linux/developers/java/minio-java.html

3.1、Java调用

3.1.1、导入jar包

  <!-- 父工程是这个,作为告知 -->
  <parent>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-parent</artifactId>
      <version>2.7.13-SNAPSHOT</version>
      <relativePath/> <!-- lookup parent from repository -->
  </parent>

  <!-- 这个才是MiniO的Maven -->
  <dependency>
      <groupId>io.minio</groupId>
      <artifactId>minio</artifactId>
      <version>8.4.3</version>
  </dependency>

3.1.2、调用

此处要引入一个概念,MiniO不直接存储文件,而是在Bucket桶中存储文件。因此在上传文件的时候需要需要指定对应的桶才能进行上传。

// 仅仅作为一个测试类进行使用,不展示详细的功能。
@SpringBootTest
class MinioServerApplicationTests {

    @Test
    void contextLoads() throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        //模拟获取一个文件流
        BufferedInputStream inputStream =
                FileUtil.getInputStream(new File("C:\\Users\\musiro\\Desktop\\A.txt"));
        //准备好一个桶
        final String bucketName = "demo";
        final String fileName = "A.txt";

        //创建客户端
        MinioClient client = MinioClient.builder()
                .endpoint("192.168.56.105",9000,false) // IP - 文件服务端口 - 是否需要SSL认证连接
                .credentials("admin", "12345678")
                .build();
        //判断桶是否存在
        boolean bucketExists = client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        //桶不存在需要创建桶
        if (!bucketExists){
            client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
        //上传文件
        int fileSize = inputStream.available();
        client.putObject(PutObjectArgs.builder()
                        .bucket(bucketName) //桶名称
                .object(fileName) //文件名称
                .stream(inputStream, fileSize, -1).build()); //文件流 - 文件大小 - 部分大小

        //下载文件
        InputStream file = client.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
        FileUtil.writeFromStream(file, new File("C:\\Users\\musiro\\Desktop\\B.txt"));
        file.close();

    }

}

3.2、Other

其他暂时不研究


4、编写工具类

该工具类只是简单的使用,如果需要完善可自行编写或者度娘,GG寻找。

minio:
  server:
    ip: 192.168.56.105
    port: 9000
  user:
    account: test
    password: 12345678

package com.musiro.minioserver;

import io.minio.*;
import io.minio.messages.Bucket;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * Minio服务的工具类,需要结合Spring一起使用
 * @author musiro
 * @date 2023/6/3
 */
@Component
@SuppressWarnings({"unused","UnusedReturnValue"})
public class MinioUtil {

    /**
     * 默认数据类型
     */
    private static final String DEFAULT_CONTENT_TYPE = "application/octet-stream";

    /**
     * 服务IP
     */
    @Value("${minio.server.ip}")
    public String serverIp;

    /**
     * 服务端口
     */
    @Value("${minio.server.port}")
    public int serverPort;

    /**
     * 账户名:此处建议创建专用用户而不适用管理员账户
     */
    @Value("${minio.user.account}")
    public String account;

    /**
     * 用户名:此处建议创建专用用户而不适用管理员账户
     */
    @Value("${minio.user.password}")
    public String password;

    /**
     * 客户端
     */
    private MinioClient client;

    @PostConstruct
    public void init(){
        client = MinioClient.builder()
                .endpoint(serverIp,serverPort,false)
                .credentials(account,password)
                .build();
    }

    /**
     * 上传文件
     * @param fileStream 文件流
     * @param bucketName 桶名
     * @param fileName 文件名称
     * @param type 数据类型
     * @return 版本ID:版本ID是桶开启对应功能后自动生成的
     */
    public String uploadFile(InputStream fileStream,String bucketName,String fileName,String type){
        try {
            int fileSize = fileStream.available();
            return client.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .contentType(type)
                    .stream(fileStream,fileSize,-1).build()).versionId();
        }catch (Exception e){
            throw new RuntimeException(e.getMessage());
        }
    }

    /**
     * 上传文件
     * @param fileStream 文件流
     * @param bucketName 桶名
     * @param fileName 文件名称
     * @return 版本ID:版本ID是桶开启对应功能后自动生成的
     */
    public String uploadFile(InputStream fileStream,String bucketName,String fileName){
        return uploadFile(fileStream,bucketName,fileName,DEFAULT_CONTENT_TYPE);
    }

    /**
     * 下载文件
     * @param bucketName 桶名
     * @param fileName 文件名
     * @return 文件流
     */
    public InputStream downloadFile(String bucketName,String fileName){
        try {
            return client.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 删除文件
     * @param bucketName 桶名
     * @param fileName 文件名称
     */
    public void removeFile(String bucketName,String fileName){
        try {
            client.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 合并文件,用于分片上传并合并
     * <br/><b>注意:</b>想要合并分片,分片大小必须大于5Mb。最后一个分片也要强行让它≥5Mb
     * @param fragmentList 分片信息
     * @param desBucketName 合并后文件所在的桶名
     * @param desFileName 合并后文件的文件名
     * @return 版本ID:版本ID是桶开启对应功能后自动生成的
     */
    public String composeFile(List<ComposeSource> fragmentList,String desBucketName,String desFileName){
        try {
            return client.composeObject(ComposeObjectArgs.builder().bucket(desBucketName).object(desFileName).sources(fragmentList).build()).versionId();
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 合并文件,用于分片上传并合并。<br/>
     * 如果分片桶都在一个桶中可以使用当前方法
     * <br/><b>注意:</b>想要合并分片,分片大小必须大于5Mb。最后一个分片也要强行让它≥5Mb
     * @param srcBucketName 如果分片的桶都存在一个桶中,
     * @param fragmentNameList 分片名称集合
     * @param desBucketName 合并后文件所在的桶名
     * @param desFileName 合并后文件的文件名
     * @return 版本ID:版本ID是桶开启对应功能后自动生成的
     */
    public String composeFile(String srcBucketName,List<String> fragmentNameList,String desBucketName,String desFileName){
        try {
            List<ComposeSource> list = new ArrayList<>();
            fragmentNameList.forEach(s -> list.add(ComposeSource.builder().bucket(srcBucketName).object(s).build()));
            return composeFile(list, desBucketName, desFileName);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    // -->桶操作<--
    // -->桶的高级操作请可视化界面操作<--

    /**
     * 创建桶
     * @param bucketName 桶名
     */
    public void createBucket(String bucketName){
        try {
            client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 判断桶是否存在
     * @param bucketName 桶名
     * @return 桶是否存在
     */
    public boolean bucketExists(String bucketName){
        try {
            return client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 删除桶
     * @param bucketName 桶名称
     */
    public void removeBucket(String bucketName){
        try {
            client.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 桶集合
     * @return 桶集合
     */
    public List<Bucket> bucketList(){
        try {
            List<Bucket> buckets = client.listBuckets();
            return client.listBuckets();
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

}

加载中..............

暂时只是看文档慢慢摸索的,已经能够完成需要的一些功能,随着后期深入会继续完善。

本文作者:Ch1ee

本文链接:https://www.cnblogs.com/daimourentop/p/17453778.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Ch1ee  阅读(1679)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起