初步搭建一个自己的对象存储服务---Minio

minio · 浏览次数 : 0

小编点评

```json { "end_point": "http://xxx.xxx.xxx.xxx:9001/", "access_key": "YLCS8UYJFX02E70OV7MK", "secret_key": "不能外露", "bucket_name": "test", "image_size": 10485760, "file_size": 1073741824 } ```

正文

docker安装

1、拉取镜像
docker pull minio/minio
2、启动镜像

docker run -p 9000:9000 -p 9001:9001 --name minio -d --restart=always -e "MINIO_ACCESS_KEY=admin" -e "MINIO_SECRET_KEY=admin123456" -v /home/data:/data -v /home/config:/root/.minio minio/minio server --console-address ":9000" --address ":9001" /data

重要:

  • -p9000 是图形界面的端口,9001 是 API 的端口,在使用 SDK 连接需要用到
  • MINIO_ACCESS_KEY:指定图形界面的用户名
  • MINIO_SECRET_KEY:指定图形界面的密码

命令参数及选项说明:

  1. docker run: 这是 Docker 的基本命令,用于运行一个新的容器。
  2. -p 9000:9000 -p 9001:9001: 使用 -p 或 --publish 选项将主机(宿主机)端口映射到容器内部端口。这里分别做了两个端口映射:
    • 9000:9000:将主机的 9000 端口与容器内的 9000 端口绑定,使得外部可以通过主机的 9000 端口访问到容器内运行的服务。
    • 9001:9001:同样地,将主机的 9001 端口与容器内的 9001 端口绑定。
  3. --name minio: 使用 --name 选项指定新创建容器的名称为 minio,便于后续管理和引用。
  4. -d: 使用 -d 或 --detach 标志使容器在后台以守护进程模式运行,即启动后立即返回控制台而不阻塞。
  5. --restart=always: 设置容器的重启策略为 always,这意味着如果容器意外停止(如由于系统重启或故障),Docker 将自动重新启动该容器。
  6. -e "MINIO_ACCESS_KEY=admin" -e "MINIO_SECRET_KEY=admin": 使用 -e 或 --env 选项设置环境变量。这里设置了 MinIO 需要的访问密钥和秘密密钥:
    • MINIO_ACCESS_KEY=admin:定义 MinIO 的访问密钥(Access Key),用于身份验证。
    • MINIO_SECRET_KEY=admin:定义 MinIO 的秘密密钥(Secret Key),与访问密钥一起构成认证凭据。
  7. -v /home/data:/data -v /home/config:/root/.minio: 使用 -v 或 --volume 选项挂载主机目录到容器内:
    • -v /home/data:/data:将主机上的 /home/data 目录挂载到容器内的 /data 目录,用于存放 MinIO 存储的数据。
    • -v /home/config:/root/.minio:将主机上的 /home/config 目录挂载到容器内的 /root/.minio 目录,通常用于保存 MinIO 的配置文件和其他持久化数据。
  8. minio/minio: 指定要使用的 Docker 镜像,这里是官方的 minio/minio 镜像。
  9. server: 运行 MinIO 容器时执行的命令,通常为 server,用于启动 MinIO 服务。
  10. --console-address ":9000" --address ":9001": 传递给 server 命令的 MinIO 特定参数:
  • --console-address ":9000":指定 MinIO 管理控制台的监听地址为 :9000,即容器内的所有网络接口都会监听此端口。由于已经做了端口映射,外部可以通过主机的 9000 端口访问控制台。
  • --address ":9001":指定 MinIO 服务 API 的监听地址为 :9001,同样对所有网络接口开放。外部可通过主机的 9001 端口与 MinIO API 进行交互。
  1. /data: 最后的 /data 参数指定了 MinIO 服务的数据目录,即使用挂载的 /data 目录作为存储桶数据的实际位置。

访问

浏览器输入http://ip:9000/login

图形界面

1、创建桶
image.png

2、设置权限
image.png

3、获取accessKey 和 secretKey
image.png

注意:创建__accessKey 和 secretKey的时候,要注意保存好。

Java连接Minio(SDK)

1、添加依赖

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

2、demo

import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.UploadObjectArgs;
import io.minio.errors.MinioException;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

public class FileUploader {
    // minio的api 端口(不是图形界面)
    public static String endPoint = "http://xxx.xxx.xxx.xxx:9001/";
    
    public static String accessKey = "YLCS8UYJFX02E70OV7MK";
    public static String secretKey = "不能外露";

    public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
        try {
            // 创建minioClient, 使用上面的endpoint,ak,sk
            MinioClient minioClient =
            MinioClient.builder()
            .endpoint(endPoint)
            .credentials(accessKey, secretKey)
            .build();

            // 如果指定的bucket不存在,则创建,否则使用已有bucket
            // 指定bucket名称
            String bucketName = "test";
            boolean found =
            minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!found) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            } else {
                System.out.println("Bucket '" + bucketName + "' already exists.");
            }

            // 文件来自哪里
            String filePath = "C:\\Users\\DELL\\Pictures\\Saved Pictures\\2.jpg";
            // 存储后的文件名
            String fileName = "minio_test_text.png";

            // 执行文件上传
            minioClient.uploadObject(
                UploadObjectArgs.builder()
                .bucket(bucketName)
                .object(fileName)
                .filename(filePath)
                .build());
            System.out.println("'" + filePath + "' 成功上传对象 '" + fileName + "' 到 bucket '" + bucketName + "'.");
        } catch (MinioException e) {
            System.out.println("Error occurred: " + e);
            System.out.println("HTTP trace: " + e.httpTrace());
        }
    }
}

封装工具类

1、配置文件

  chuangyue:
    minio:
      # 访问的url
      endpoint: http://xxx.xxx.xxx.xxx
      # API的端口
      port: 9001
      # 秘钥
      accessKey: YLCS8UYJFX02E70OV7MK
      secretKey: 不能看
      secure: false
      bucket-name: test # 桶名 我这是给出了一个默认桶名
      image-size: 10485760 # 我在这里设定了 图片文件的最大大小
      file-size: 1073741824 # 此处是设定了文件的最大大小

2、属性配置类

@Component
@ConfigurationProperties(prefix = "chuangyue.minio")
@Data
public class MinioProperties {
    // 访问的 api 的url
    private String endpoint;
    // api端口号
    private String port;
    // 密钥
    private String accessKey;
    private String secretKey;
    private Boolean secure;
    // 桶名
    private String bucketName;
    // 图片文件的最大大小
    private long imageSize;
    // 文件的最大大小
    private long fileSize;
}

3、工具类

package com.zyp.utils;

import io.minio.*;
import io.minio.errors.MinioException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;

@Component
@Slf4j
public class MinioUtil {
    
    /**
     * @ description 上传
     * @param file 文件
     * @param endPoint 访问的地址
     * @param port 端口号
     * @param accessKey 密钥
     * @param secretKey 密钥
     * @param bucketName 桶名称
     * @ return java.lang.String
     * @ author DELL
     */
    public static String upload(MultipartFile file, String endPoint, String port, String accessKey, String secretKey, String bucketName) throws IOException, NoSuchAlgorithmException, InvalidKeyException {
        try {
            // 创建minioClient
            MinioClient minioClient =
                    MinioClient.builder()
                            .endpoint(endPoint + ":" + port)
                            .credentials(accessKey, secretKey)
                            .build();

            // 如果指定的bucket不存在,则创建,否则使用已有bucket
            boolean found =
                    minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!found) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            } else {
                log.info("Bucket {} already exists", bucketName);
            }

            // 获取文件原始名称
            String oringinalName = file.getOriginalFilename();
            // 获取后缀
            String suffix = oringinalName.substring(oringinalName.lastIndexOf('.'));
            // 拼接存储后的文件名
            String fileName = UUID.randomUUID().toString() + suffix;

            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(fileName)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build();

            minioClient.putObject(putObjectArgs);
            log.info("文件上传成功");

            // 拼接url并返回
            return endPoint + ":" + port + "/" + bucketName + "/" + fileName;

        } catch (MinioException e) {
            System.out.println("Error occurred: " + e);
            System.out.println("HTTP trace: " + e.httpTrace());
            return "error";
        }
    }
}

4、使用,定义一个文件上传的接口

@RestController
@Slf4j
public class FileUploadController {
    @Autowired
    private MinioProperties minioProperties;

    /**
     * @ description 文件上传
     * @param file
     * @ return com.zyp.pojo.Result<java.lang.String>
     * @ author DELL
     */
    @PostMapping("/upload")
    public Result<String> upload(MultipartFile file) throws Exception {

        String url = MinioUtil.upload(file, minioProperties.getEndpoint(), minioProperties.getPort(), minioProperties.getAccessKey(), minioProperties.getSecretKey(), minioProperties.getBucketName());
        log.info("url= {}",url);

        if(url.isEmpty() || url.equals("error")){
            throw new UploadErrorException("文件上传失败");
        }else{
            return Result.success(url);
        }
    }
}

常见问题

1、tomcat限制了文件上传或者下载的大小
解决:修改配置文件

spring:
  servlet:
    multipart:
      max-file-size: 50MB
      max-request-size: 50MB

与初步搭建一个自己的对象存储服务---Minio相似的内容:

初步搭建一个自己的对象存储服务---Minio

MinIO 是一个高性能的对象存储解决方案,类似于 Amazon S3,但它是开源的。MinIO 可以用于存储大规模的不结构化数据,比如照片、视频、备份和日志文件等。它设计为兼容 Amazon S3 API,因此可以很容易地与现有的使用 S3 的应用程序集成。

《最新出炉》系列初窥篇-Python+Playwright自动化测试-3-离线搭建playwright环境

1.简介 有些小伙伴或者童鞋们私信留言说自己是在公司局域网办公,或者公司为了安全对网络管控比较严格(尤其是一些大的国企、央企),总之就是一句话无法连到外网去在线下载,宏哥刚看到留言时觉得这问题还留言问啊,你找个有网的电脑下载好安装包然后安装就可以用了。(第一种情况及解决办法:带要搭建环境的电脑到有网

4.Autofac依赖注入初使用

前面几篇文章只是初步搭建项目结构,那到底能否运行呢?(能是肯定的啦) 毕竟咱都NetCore了,所以依赖注入要搞起来。专业的解释我就不多说了,很多博客文章说的很详细(其实是我忘了那些术语怎么讲)。 按照我的理解来说的话就是: 省的你自己手动new了,假如你要更改接口,那不就要每个new的地方都改一下

AI音乐创作,让每一个人都成为音乐家

从录音带、MP3到专业的耳机、音箱,随着音乐消费方式的不断升级,音乐创作的专业“门槛”也在AI技术的加持下逐渐大众化,创作者的创新设计、创作频率也在持续增强,能降低创作门槛且智能化的创作工具就显得尤为重要。 怀揣着“人人都能玩点音乐”的初衷,唱鸭搭建了自己的音乐社区,希望为普通用户提供智能有趣的音乐

企业内部培训网站为例,探索云上成本优化

摘要:本文就以一个企业内部培训网站为例,拆解云上成本优化方案需要注意的点,抛砖引玉,帮助大家参考业务架构,合理节省费用。 本文分享自华为云社区《云上成本优化方案——以一个企业内部培训网站为例》,作者:云存储开发者支持团队。 越来越多的企业选择将服务搭建在云上,业务初期访问量、数据量都较小,成本问题还

初识上位机(上):搭建PLC模拟仿真环境

作为一个工业自动化领域的程序员,不懂点PLC和上位机,貌似有点说不过去。这里我用两篇小文带你快速进入上位机开发领域。首先,我们先要搭建一个PLC的模拟仿真环境,以便后续能够使用C#开发上位机程序。

初识上位机(下):C#读写PLC数据块数据

作为一个工业自动化领域的程序员,不懂点PLC和上位机,貌似有点说不过去。这里我用两篇小文带你快速进入上位机开发领域。上一篇,我们搭建了一个PLC的模拟仿真环境,本篇我们使用C#开发一个简单的PLC数据读取和写入的应用程序。

虚拟化技术浅析第二弹之初识Kubernetes

作者:京东物流 杨建民 一、微服务架构起源 单体架构:可以理解为主要业务逻辑模块(我们编写的代码模块,不包括独立的中间件)运行在一个进程中的应用,最典型的是运行在一个Tomcat容器中,位于一个进程里。单体架构好处是技术门槛低、编程工作量少、开发简单快捷、调试方便、环境容易搭建、容易发布部署及升级,

个人和初创企业想要搭建网站,如何挑选一台便宜合适的云主机?

一台云服务器,除了域名备案外,可以做很多事情,个人可以使用云服务器部署个人博客系统、论坛系统、私人网盘,部署各种后端服务,企业主要用来网站建设,适用于社区网站、企业官网、门户网站、电子商务网站、游戏类等各种应用,还可以用来数据库应用、制图渲染等等。 个人搭建博客、小型网站的话,1核2G配置即可。对于

《最新出炉》系列初窥篇-Python+Playwright自动化测试-2-playwright的API及其他知识

1.简介 上一篇宏哥已经将Python+Playwright的环境搭建好了,而且也简单的演示了一下三款浏览器的启动和关闭,是不是很简单啊。今天主要是把一篇的中的代码进行一次详细的注释,然后说一下playwright的API和其他相关知识点。那么首先将上一篇中的代码进行一下详细的解释。 2.代码解释