首页 > 其他分享 >MinIO的简单使用

MinIO的简单使用

时间:2023-11-24 15:16:42浏览次数:38  
标签:MinIO return String 简单 fileName file 使用 public minio

MINIO介绍

什么是对象存储?

以阿里云OSS为例:

对象存储服务OSS(Object Storage Service)是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。
优势就在于它可以存储大容量的非结构化数据。
缺点:没有选择业务上云或者想要下云的企业,使用公有云的 OSS,在公网带宽方面就需要有一定的投入,毕竟需要通过公网传输,带宽太小,传输速度就会慢,且在传输过程中数据的安全性和完整性也有损失的风险,走专线的费用又十分昂贵,不实在。
此时MinIO 就是一个不错的选择,麻雀虽小,五脏俱全,企业可以以此快速构建自己内部的对象存储服务。

什么是minio?

Minio 是个基于 Golang 编写的开源对象存储套件,基于Apache License v2.0开源协议,虽然轻量,却拥有着不错的性能。
可以很简单的和NodeJS、Redis、MySQL等结合使用。

minio结构:

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

minio特性:

高性能、可扩展、云原生、图形化界面、支持纠删码。除了Minio自己的文件系统,还支持 DAS、 JBODs、NAS、Google云存储和 Azure Blob存储。Minio服务器通过其兼容AWS SNS / SQS的事件通知服务触发Lambda功能。支持的目标是消息队列,如Kafka,NATS,AMQP,MQTT,Webhooks以及Elasticsearch,Redis,Postgres和MySQL等数据库。

minio使用:

1.下载:

  • 官网: https://docs.min.io/
  • 说明:各个平台都能装,常见在linux服务器中使用(这里以centos为例)。
    1.在home目录下创建minio文件夹
    mkdir /home/minio
    2、进入/home/minio 文件夹
    cd /home/minio
    3、下载文件
    wget https://dl.min.io/server/minio/release/linux-amd64/minio
    注意:如果上一行报错,请先运行yun install wget
    4.创建数据文件夹
    mkdir /home/minio/data
    mkdir /home/minio/log
    5.创建日志文件
    touch /home/minio/log/minio.log
    6.启动
    6.1赋予权限
    chmod 777 minio
    6.2.1前台启动命令
    ./minio server /home/minio/data
    6.2.2后台启动命令
    nohup ./minio server /home/minio/data > /home/minio/log/minio.log &
    7.修改超管账户名和密码(为了安全)
    7.1打开 /etc/profile 文件
    vim /etc/profile
    7.2在文件的最末尾加上以下信息
    注意看提示,新版本需要用MINIO_ROOT_USER和MINIO_ROOT_PASSWORD,
    旧版需要用MINIO_ACCESS_KEY和MINIO_SECRET_KEY
    按 i 键后,在文档末尾输入
    (新版)
            export MINIO_ROOT_USER=minioadmin
            export MINIO_ROOT_PASSWORD=你想改的密码
    (旧版)
            export MINIO_ACCESS_KEY=minioadmin
            export MINIO_SECRET_KEY=你想改的密码
    8.保存退出esc   :wq
    9.重载配置
            source /etc/profile
    10.打开127.0.0.1:9000 即可看到运行页面

  • 关闭后台minio
    1.通过命令查看端口
    ps -aux | grep minio
    2.kill杀死进程
    kill -9 进程号(五位数字) 
    3.开放下载,设置永久链接
    3.1下载客户端
    wget https://dl.minio.io/client/mc/release/linux-amd64/mc
    3.2赋予权限
    chomd 777mc
    3.3添加server
    ./mc config host add minio htt//你的ip:9000/ minioadmin 你的minio密码
    3.4设置需要开放下载的bucket
    ./mc anonymous set download minio/dev
    4.文件访问地址:
    http://你的ip:9000/dev/年/月/日/文件名

minio在springboot中使用

1.导入依赖 刷新maven

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

2.在application.yml中新增配置

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

3.java代码接口

 /**
     * 文件上传至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;
    }


若依Java接口

/**
 * 自定义 Minio 服务器上传请求
 */
@PostMapping("/uploadMinio")
public AjaxResult uploadFileMinio(MultipartFile file) throws Exception
{
	try
	{
		// 上传并返回新文件名称
		String fileName = FileUploadUtils.uploadMinio(file);
		AjaxResult ajax = AjaxResult.success();
		ajax.put("url", fileName);
		ajax.put("fileName", fileName);
		ajax.put("newFileName", FileUtils.getName(fileName));
		ajax.put("originalFilename", file.getOriginalFilename());
		return ajax;
	}
	catch (Exception e)
	{
		return AjaxResult.error(e.getMessage());
	}
}


文件上传工具类

package com.ruoyi.common.utils.file;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.Objects;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.config.MinioConfig;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException;
import com.ruoyi.common.exception.file.FileSizeLimitExceededException;
import com.ruoyi.common.exception.file.InvalidExtensionException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.Seq;

/**
 * 文件上传工具类
 * 
 * @author ruoyi
 */
public class FileUploadUtils
{
    /**
     * 默认大小 50M
     */
    public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024;

    /**
     * 默认的文件名最大长度 100
     */
    public static final int DEFAULT_FILE_NAME_LENGTH = 100;

    /**
     * 本地默认上传的地址
     */
    private static String defaultBaseDir = RuoYiConfig.getProfile();
    
    /**
     * Minio默认上传的地址
     */
    private static String bucketName = MinioConfig.getBucketName();

    public static void setDefaultBaseDir(String defaultBaseDir)
    {
        FileUploadUtils.defaultBaseDir = defaultBaseDir;
    }

    public static String getDefaultBaseDir()
    {
        return defaultBaseDir;
    }
    
    public static String getBucketName()
    {
        return bucketName;
    }

    /**
     * 以默认配置进行文件上传
     *
     * @param file 上传的文件
     * @return 文件名称
     * @throws Exception
     */
    public static final String upload(MultipartFile file) throws IOException
    {
        try
        {
            return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }

    /**
     * 根据文件路径上传
     *
     * @param baseDir 相对应用的基目录
     * @param file 上传的文件
     * @return 文件名称
     * @throws IOException
     */
    public static final String upload(String baseDir, MultipartFile file) throws IOException
    {
        try
        {
            return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }

    /**
     * 文件上传
     *
     * @param baseDir 相对应用的基目录
     * @param file 上传的文件
     * @param allowedExtension 上传文件类型
     * @return 返回上传成功的文件名
     * @throws FileSizeLimitExceededException 如果超出最大大小
     * @throws FileNameLengthLimitExceededException 文件名太长
     * @throws IOException 比如读写文件出错时
     * @throws InvalidExtensionException 文件校验异常
     */
    public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
            InvalidExtensionException
    {
        int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
        {
            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
        }

        assertAllowed(file, allowedExtension);

        String fileName = extractFilename(file);

        String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
        file.transferTo(Paths.get(absPath));
        return getPathFileName(baseDir, fileName);
    }

    /**
     * 以默认BucketName配置上传到Minio服务器
     *
     * @param file 上传的文件
     * @return 文件名称
     * @throws Exception
     */
    public static final String uploadMinio(MultipartFile file) throws IOException
    {
        try
        {
            return uploadMinino(getBucketName(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }
    
    /**
     * 自定义bucketName配置上传到Minio服务器
     *
     * @param file 上传的文件
     * @return 文件名称
     * @throws Exception
     */
    public static final String uploadMinio(MultipartFile file, String bucketName) throws IOException
    {
        try
        {
            return uploadMinino(bucketName, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }

    private static final String uploadMinino(String bucketName, MultipartFile file, String[] allowedExtension)
            throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
            InvalidExtensionException
    {
        int fileNamelength = file.getOriginalFilename().length();
        if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
        {
            throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
        }
        assertAllowed(file, allowedExtension);
        try
        {
            String fileName = extractFilename(file);
            String pathFileName = MinioUtil.uploadFile(bucketName, fileName, file);
            return pathFileName;
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }

    /**
     * 编码文件名
     */
    public static final String extractFilename(MultipartFile file)
    {
        return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
                FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
    }

    public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
    {
        File desc = new File(uploadDir + File.separator + fileName);

        if (!desc.exists())
        {
            if (!desc.getParentFile().exists())
            {
                desc.getParentFile().mkdirs();
            }
        }
        return desc;
    }

    public static final String getPathFileName(String uploadDir, String fileName) throws IOException
    {
        int dirLastIndex = RuoYiConfig.getProfile().length() + 1;
        String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
        return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
    }

    /**
     * 文件大小校验
     *
     * @param file 上传的文件
     * @return
     * @throws FileSizeLimitExceededException 如果超出最大大小
     * @throws InvalidExtensionException
     */
    public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
            throws FileSizeLimitExceededException, InvalidExtensionException
    {
        long size = file.getSize();
        if (size > DEFAULT_MAX_SIZE)
        {
            throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
        }

        String fileName = file.getOriginalFilename();
        String extension = getExtension(file);
        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
        {
            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
                        fileName);
            }
            else
            {
                throw new InvalidExtensionException(allowedExtension, extension, fileName);
            }
        }
    }

    /**
     * 判断MIME类型是否是允许的MIME类型
     *
     * @param extension
     * @param allowedExtension
     * @return
     */
    public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
    {
        for (String str : allowedExtension)
        {
            if (str.equalsIgnoreCase(extension))
            {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取文件名的后缀
     * 
     * @param file 表单文件
     * @return 后缀名
     */
    public static final String getExtension(MultipartFile file)
    {
        String extension = FilenameUtils.getExtension(file.getOriginalFilename());
        if (StringUtils.isEmpty(extension))
        {
            extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
        }
        return extension;
    }
}

MinioConfig.java

package com.ruoyi.common.config;

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

/**
 * Minio 配置信息
 *
 * @author ruoyi
 */
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig
{
    /**
     * 服务地址
     */
    private static String url;

    /**
     * 用户名
     */
    private static String accessKey;

    /**
     * 密码
     */
    private static String secretKey;

    /**
     * 存储桶名称
     */
    private static String bucketName;

    public static String getUrl()
    {
        return url;
    }

    public void setUrl(String url)
    {
        MinioConfig.url = url;
    }

    public static String getAccessKey()
    {
        return accessKey;
    }

    public void setAccessKey(String accessKey)
    {
        MinioConfig.accessKey = accessKey;
    }

    public static String getSecretKey()
    {
        return secretKey;
    }

    public void setSecretKey(String secretKey)
    {
        MinioConfig.secretKey = secretKey;
    }

    public static String getBucketName()
    {
        return bucketName;
    }

    public void setBucketName(String bucketName)
    {
        MinioConfig.bucketName = bucketName;
    }

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

MinioUtil.java

package com.ruoyi.common.utils.file;

import java.io.IOException;
import java.io.InputStream;
import org.springframework.web.multipart.MultipartFile;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.http.Method;

/**
 * Minio 文件存储工具类
 * 
 * @author ruoyi
 */
public class MinioUtil
{
    /**
     * 上传文件
     * 
     * @param bucketName 桶名称
     * @param fileName
     * @throws IOException
     */
    public static String uploadFile(String bucketName, String fileName, MultipartFile multipartFile) throws IOException
    {
        String url = "";
        MinioClient minioClient = SpringUtils.getBean(MinioClient.class);
        try (InputStream inputStream = multipartFile.getInputStream())
        {
            minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(inputStream, multipartFile.getSize(), -1).contentType(multipartFile.getContentType()).build());
            url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(fileName).method(Method.GET).build());
            url = url.substring(0, url.indexOf('?'));
            return ServletUtils.urlDecode(url);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }
}

标签:MinIO,return,String,简单,fileName,file,使用,public,minio
From: https://www.cnblogs.com/guobabiancheng/p/17853762.html

相关文章

  • gitlab runner 使用摘要
    参考文档GitLabRunnerrunstheCI/CDjobsthataredefinedinGitLabGitLabRunnerisopen-sourceandwritteninGo.Itcanrunasasinglebinaryandhasnolanguage-specificrequirements.AfteryouinstallGitLabRunner,youmustcreateandregisterrunne......
  • Gitlab Docker 使用摘要
    官方文档:https://docs.gitlab.com/ee/install/docker.html#expose-gitlab-on-different-ports设置本地目录设置环境变量GITLAB_HOMEexportGITLAB_HOME=/srv/gitlab安装启动脚本start.sh#!/bin/bashexportGITLAB_HOME=/srv/gitlabsudodockerrun--detach......
  • 一文讲明Mybatis 的使用 超详细 【爆肝两万字教程】
    >我|在这里>......
  • 使用CloudStats监控Linux服务器
    CloudStats是一个服务器监控平台,可让您轻松地监控整个服务器基础平台,同时也可以立即采取行动并解决问题。CloudStats监控工具不需要任何特殊技能或知识来执行设置并开始监控您的服务器。因为是国外的服务器,打开有点慢!在服务器( /Debian/Ubuntu/Fedora等)上安装CloudStats......
  • Java中使用try-with-resources
    Java7中引入的对资源 try-with-resources ,声明在 try 块中使用的资源,并保证资源将在该块执行后关闭。声明的资源需要实现自动关闭接口。 1.使用资源try典型的try-catch-finally块:Scannerscanner=null;try{scanner=newScanner(newFile("test.txt"));......
  • 使用golang写一个导出excel的接口
    Craftedby[Genie](https://marketplace.visualstudio.com/items?itemName=genieai.chatgpt-vscode)You使用golang写一个导出excel的接口Genie要创建一个使用Go语言编写的导出Excel文件的接口,我们需要做几个步骤:安装依赖:我们将使用excelize库来创建和操作Excel文件。......
  • 简单的应急响应练习
    利用Windowsserver2003简单搭建一个存在木马的靶机,供同学们接触了解应急响应的基础技巧场景如下:存在一台web服务器,已被入侵,如何去排查解决此次安全事件 首先根据通常经验,会查一下服务器外联情况,通过netstat-ano查看,发现PID2332存在不正常的外部链接通过PID定位到具体......
  • How to use 微PE to install WinOS. 怎么使用微PE安装系统.(no USB drive)
    1.Download微PEInstallit.https://www.wepe.com.cn/download.html 2.Rebootyoursystem,Select微PEtostart. 3. OpenCGI备份还原  .Tips.Step3,chooseyoursystem's partition.Don'tmistake.Mindit'ssize.Forexample,my......
  • easydict的使用方法
    EasyDict是FluentDict的一个分支,它为Python字典提供了一种更简洁的访问方式。使用EasyDict,您可以像访问属性一样访问字典的键和值,而无需使用方括号和键。以下是EasyDict的常用方法:1.创建EasyDict对象:通过将一个字典传递给EasyDict构造函数来创建一个EasyDict对象。例如:fromeasy......
  • 简单的低开编辑器(三):实现组件画布内拖拽
    好家伙,0.代码已开源Fattiger4399/lowcode-demo:一个简单的低代码编辑器技术栈:Vue3element-plusjsx(github.com) 本篇实现效果如下: 1.分析这玩意的思路很好理解本质上就是给组件绑个拖拽方法拽到哪里,就把位置更新给组件就好了,简单粗暴当然,需要做选中判定,知道我......