首页 > 系统相关 >Linux+Docker:3分钟实现MinIO在线部署与Java集成

Linux+Docker:3分钟实现MinIO在线部署与Java集成

时间:2024-09-14 18:23:53浏览次数:3  
标签:Java minio return bucketName Linux import Docker public String

Linux下使用Docker安装MinIO

1. 拉取 MinIO 镜像

docker pull minio/minio

2. 创建挂载目录

mkdir -p /opt/minio/data
mkdir -p /optl/minio/config

3. 检查端口占用

sudo lsof -i :9000
...

4. 启动 MinIO 容器

docker run --name minio \   # 容器名称
  -p 9010:9000 \            # 映射主机端口9010到容器端口9000
  -p 9020:9020 \            # 映射主机端口9020到容器端口9020
  -d --restart=always \     # 容器重启策略:系统启动时自动重启
  -e "MINIO_ROOT_USER=admin" \ # MinIO 管理员用户名
  -e "MINIO_ROOT_PASSWORD=admin2minio" \ # MinIO 管理员密码 这里的密码需要大于8位不如有报错
  -v "/opt/minio/data:/data" \ # 数据存储目录
  -v "/opt/minio/config:/root/.minio" \ # 配置文件目录
  minio/minio server /data --console-address ":9020" # 启动MinIO服务并指定控制台端口

5. 配置防火墙(如果有需要)

sudo firewall-cmd --zone=public --add-port=9010/tcp --permanent
sudo firewall-cmd --reload

6. 查看容器内的 MinIO 服务状态

docker exec -it minio /bin/sh
netstat -tuln

7. 检查容器日志

docker logs minio

可能会遇到的问题

1. RequestTimeTooSkewed 错误:

问题:客户端请求的时间与服务器时间的差异过大。MinIO要求客户端和服务器的时间同步。

解决方案:确保客户端和服务器的系统时间同步,或手动调整时间。查看时间的命令:

linux时间查看命令

date
2. MINIO_ROOT_PASSWORD 长度问题

问题: MinIO 对管理员密码有长度要求,密码必须至少 8 位字符,以保证安全性。短密码可能导致配置错误或安全问题。

解决方案:确保设置的 MINIO_ROOT_PASSWORD 至少为 8 位字符。检查密码是否符合 MinIO 的长度和复杂性要求。

  • 停止 MinIO 容器:
docker stop minio
  • 删除 MinIO 容器:
docker rm minio
  • 重新运行 MinIO 容器:
docker run --name minio \   
  -p 9010:9000 \            
  -p 9020:9020 \            
  -d --restart=always \     
  -e "MINIO_ROOT_USER=admin" \ 
  -e "MINIO_ROOT_PASSWORD=admin2minio" \ 
  -v "/opt/minio/data:/data" \ 
  -v "/opt/minio/config:/root/.minio" \ 
  minio/minio server /data --console-address ":9020"

确保重新运行时,密码满足要求,并且所有路径和端口正确配置。

Java项目集成MinIO

1. 添加Maven依赖

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

<dependency>
    <groupId>com.squareup.okhttp3</groupId>
    <artifactId>okhttp</artifactId>
    <version>4.9.3</version>
</dependency>

2. 配置 application.yml

minio:
  endpoint: http://ip:9010/  # MinIO服务的地址
  accessKey: 'your-access-key'  # MinIO的访问密钥
  secretKey: 'your-secret-key'  # MinIO的秘密密钥
  bucketName: test  # 默认的桶名称

3. 配置 MinIO 客户端

import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MinioConfig {

    @Value("${minio.endpoint}")
    private String endpoint;

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

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

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

4. MinIO 工具类

import com.github.pagehelper.util.StringUtil;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import io.minio.messages.Item;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Component
public class MinIoUtils {

    @Autowired
    private MinioClient minioClient;

    @Value("${minio.bucketName}")
    private String bucketName;
    /**
     * description: 判断bucket是否存在,不存在则创建
     *
     * @return: void
     */
    public boolean existBucket(String name) {
        boolean exists;
        try {
            exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(name).build());
            if (!exists) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(name).build());
                exists = true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            exists = false;
        }
        return exists;
    }

    /**
     * 创建存储bucket
     *
     * @param bucketName 存储bucket名称
     * @return Boolean
     */
    public Boolean makeBucket(String bucketName) {
        try {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 删除存储bucket
     *
     * @param bucketName 存储bucket名称
     * @return Boolean
     */
    public Boolean removeBucket(String bucketName) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * description: 上传文件
     *
     * @param file
     * @return: java.lang.String
     */
    public String upload(MultipartFile file, String fileName, String bucketNameStr) {
        InputStream in = null;
        try {
            if (StringUtil.isEmpty(bucketNameStr)) {
                bucketNameStr = bucketName;
            }
            in = file.getInputStream();
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketNameStr)
                    .object(fileName)
                    .stream(in, in.available(), -1)
                    .contentType(file.getContentType())
                    .build()
            );
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return bucketNameStr + "/" + fileName;
    }

    /**
     * description: 下载文件
     *
     * @param fileName
     * @return: org.springframework.http.ResponseEntity<byte [ ]>
     */
    public ResponseEntity<byte[]> download(String bucketNameStr, String fileName) {
        ResponseEntity<byte[]> responseEntity = null;
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try {
            if (StringUtil.isEmpty(bucketNameStr)) {
                bucketNameStr = bucketName;
            }
            in = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
            out = new ByteArrayOutputStream();
            IOUtils.copy(in, out);
            //封装返回值
            byte[] bytes = out.toByteArray();
            HttpHeaders headers = new HttpHeaders();
            try {
                headers.add("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            headers.setContentLength(bytes.length);
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setAccessControlExposeHeaders(Arrays.asList("*"));
            responseEntity = new ResponseEntity<byte[]>(bytes, headers, HttpStatus.OK);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return responseEntity;
    }

    /**
     * 查看文件对象
     *
     * @param bucketName 存储bucket名称
     * @return 存储bucket内文件对象信息
     */
    public List<ObjectItem> listObjects(String bucketName) {
        Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(bucketName).build());
        List<ObjectItem> objectItems = new ArrayList<>();
        try {
            for (Result<Item> result : results) {
                Item item = result.get();
                ObjectItem objectItem = new ObjectItem();
                objectItem.setObjectName(item.objectName());
                objectItem.setSize(item.size());
                objectItems.add(objectItem);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return objectItems;
    }

    /**
     * 批量删除文件对象
     *
     * @param bucketName 存储bucket名称
     * @param objects    对象名称集合
     */
    public Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> objects) {
        List<DeleteObject> dos = objects.stream().map(e -> new DeleteObject(e)).collect(Collectors.toList());
        Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());
        return results;
    }

    /**
     * 根据文件名和桶获取文件路径
     *
     * @param bucketName 存储bucket名称
     */
    public String getFileUrl(String bucketName, String objectFile) {
        try {
            if(StringUtil.isEmpty(bucketName)){
                bucketName = this.bucketName;
            }
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(bucketName)
                    .object(objectFile)
                    .build()
            );
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

5. api

import com.alibaba.fastjson.JSONObject;
import com.njmh.authority.utils.MinIoUtils;
import com.njmh.authority.utils.ObjectItem;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

@RestController
@RequestMapping("/minio")
public class MinioApi {


    @Autowired
    private MinIoUtils minioUtils;
    @Value("${minio.endpoint}")
    private String address;
    @Value("${minio.bucketName}")
    private String bucketName;

    @PostMapping("/upload")
    public Object upload(@RequestParam(value = "file") MultipartFile file, @RequestParam("bucketName") String bucketName) {
        return address + "/"  + minioUtils.upload(file, file.getOriginalFilename(), bucketName);
    }

    @PostMapping("/getListByBucket")
    public List<ObjectItem> getListByBucket() {
        List<ObjectItem> list = minioUtils.listObjects(bucketName);
        return list;
    }

    @PostMapping("/existBucket")
    public boolean existBucket(@RequestBody JSONObject jsonObject) {
        return minioUtils.existBucket(jsonObject.getString("name"));
    }

    @PostMapping("/makeBucket")
    public boolean makeBucket(@RequestBody JSONObject jsonObject) {
        return minioUtils.makeBucket(jsonObject.getString("name"));
    }

    @PostMapping("/removeBucket")
    public boolean removeBucket(@RequestBody JSONObject jsonObject) {
        return minioUtils.removeBucket(jsonObject.getString("name"));
    }

    @PostMapping("/getFileUrl")
    public String  getFileUrl(@RequestBody JSONObject jsonObject) {
        return minioUtils.getFileUrl(jsonObject.getString("bucketName"),jsonObject.getString("fileName"));
    }

    @GetMapping("/loadFile")
    @ResponseBody
    public ResponseEntity<?> loadFile(@RequestParam("bucketName") String bucketName,
                                      @RequestParam("filePath") String filePath) {
        return minioUtils.download(bucketName,filePath);
    }
}

标签:Java,minio,return,bucketName,Linux,import,Docker,public,String
From: https://blog.csdn.net/qq_44711486/article/details/142179356

相关文章

  • 全面的 Java 学习路线:从零基础到高级开发
    全面的Java学习路线:从零基础到高级开发Java是一门经典且广泛使用的编程语言,不仅用于企业级应用开发,也在Android开发、分布式系统、云计算等领域中占据重要地位。对于想要学习或深入掌握Java的开发者来说,清晰的学习路线至关重要。本文将为你详细梳理从初学到高级的J......
  • JAVA毕业设计171—基于Java+Springboot+vue3+小程序的宠物店小程序系统(源代码+数据库
    毕设所有选题:https://blog.csdn.net/2303_76227485/article/details/131104075基于Java+Springboot+vue3+小程序的宠物店小程序系统(源代码+数据库)171一、系统介绍本项目前后端分离(可以改为ssm版本),分为用户、店员、管理员三种角色1、用户:注册、登录、宠物购买(评论......
  • java springboot监听事件和处理事件
    在SpringBoot中,监听和处理事件是一种常用的模式,用于在应用程序的不同部分之间传递信息。Spring的事件发布/订阅模型允许我们创建自定义事件,并在这些事件发生时由注册的监听器进行处理。这里,我将提供一个简单的SpringBoot应用程序示例,其中将包括事件的定义、事件的发布以及事......
  • JAVA毕业设计174—基于Java+Springboot+vue3+小程序的农产品社区团购小程序系统(源代
    毕设所有选题:https://blog.csdn.net/2303_76227485/article/details/131104075基于Java+Springboot+vue3+小程序的农产品社区团购小程序系统(源代码+数据库+开题+万字论文)174一、系统介绍本项目前后端分离(可以改为ssm版本),分为用户、管理员两种角色1、用户:注册、登......
  • 020、二级Java选择题综合知识点(持续更新版)
    1.排序二叉树的遍历结果为有序序列的是:中序遍历解释:中序遍历是一种遍历二叉树的方式,按照“左子树->根节点->右子树”的顺序访问节点。在排序二叉树(BST)中,这种遍历顺序会得到一个递增的有序序列,因为左子树中的所有节点值都小于根节点,而右子树中的节点值都大于根节点。......
  • 记一次 公司.NET项目部署在Linux环境压测时 内存暴涨分析
    一:背景讲故事公司部署在某碟上的项目在9月份压测50并发时,发现某个容器线程、内存非正常的上涨,导致功能出现了异常无法使用。根据所学,自己分析了下线程和内存问题,分析时可以使用lldb或者windbg,但是个人比较倾向于界面化的windbg,所以最终使用windbg开干。二:WinDbg分析到底是......
  • 基于Java实现的漫画之家系统设计与实现(SpringBoot+Vue+MySQL+Tomcat)
    文章目录1.前言2.详细视频演示3.论文参考4.项目运行截图5.技术框架5.1后端采用SpringBoot框架5.2前端框架Vue6.选题推荐毕设案例8.系统测试8.1系统测试的目的8.2系统功能测试9.代码参考10.为什么选择我?11.获取源码1.前言......
  • 基于Java实现的家政服务管理平台设计与实现(SpringBoot+Vue+MySQL+Tomcat)
    文章目录1.前言2.详细视频演示3.论文参考4.项目运行截图5.技术框架5.1后端采用SpringBoot框架5.2前端框架Vue6.选题推荐毕设案例8.系统测试8.1系统测试的目的8.2系统功能测试9.代码参考10.为什么选择我?11.获取源码1.前言......
  • Java 与大数据:Hadoop 和 Spark 的完美集成
    ......
  • 切换到淘宝最新 npm 镜像源的全面指南(支持 Windows、macOS 和多种 Linux 发行版)
    切换到淘宝最新npm镜像源的全面指南(支持Windows、macOS和多种Linux发行版)在开发过程中,npm是前端开发者不可或缺的工具。但对于国内的开发者来说,npm官方源在下载速度上存在一定的瓶颈。淘宝npm镜像源同步了官方库,并提供了更快的访问速度。本文将详细介绍如何在Wi......