当前位置: 首页 > news >正文

SpringBoot教程(三十三)| SpringBoot集成MinIO

SpringBoot教程(三十三)| SpringBoot集成MinIO

  • 一、MinIO 是什么?
  • 二、MinIO 与主流存储方案的对比分析
  • 三、MinIO 适用场景界定
  • 四、Windows 环境下 MinIO 部署与配置
    • 1. 下载 MinIO
    • 2. 启动 MinIO
    • 3. 汉化操作
    • 4. MinIO 核心概念解析
    • 5. MinIO 基础操作指南(Web 控制台)
  • 五、SpringBoot集成MinIO
    • 1. 引入maven
    • 2. 配置 MinIO 连接信息
    • 3. 创建 MinIO 客户端配置类
    • 4. 封装 MinIO 工具类
    • 5. 编写测试接口
    • 6. 测试验证

一、MinIO 是什么?

MinIO 是一款基于对象存储模型的高性能开源存储方案,采用 Go 语言开发,具备轻量部署、高可用、可扩展等核心特性。
其核心价值在于为用户提供私有化对象存储服务——通过将本地磁盘或服务器存储资源转化为标准化的对象存储服务,实现对图片、视频、文档等非结构化数据的高效管理,同时支持 API 集成、权限管控、数据备份等企业级能力,兼顾个人测试与生产环境部署需求。

二、MinIO 与主流存储方案的对比分析

为明确 MinIO 的适用场景,以下从存储模型、部署方式、核心优势等维度,将其与常见存储方案进行对比:

存储方案存储模型部署模式核心优势适用场景局限性
MinIO对象存储单机/分布式轻量部署、高可用、API 兼容 S3、私有化可控企业私有化文件存储、业务数据备份、开发测试环境需自行维护服务器硬件与部署环境
本地磁盘存储(Ext4/NTFS)文件系统单机本地部署零成本、操作直观个人临时存储、单节点小型工具无共享能力、扩容受限、数据可靠性低
公有云对象存储(OSS/COS)对象存储公有云托管零运维、弹性扩容、按需付费无私有化需求的互联网业务、轻量级应用数据归属第三方、长期使用成本较高
分布式文件系统(FastDFS)文件系统集群部署高并发访问支持、适合大文件存储短视频平台、海量日志存储等超大规模场景部署复杂度高、运维成本高、适配门槛高

三、MinIO 适用场景界定

  1. 私有化部署场景:企业对数据私密性要求较高(如合同文档、内部研发资料),需将数据存储在自有服务器集群,MinIO 可通过分布式部署实现数据本地化管控。

  2. 业务数据存储场景:电商平台商品图片、社交 APP 用户头像、教育平台课程视频等非结构化数据存储,MinIO 支持高并发读写,适配业务流量波动。

  3. 开发测试场景:开发者需快速搭建轻量化存储服务用于功能测试,MinIO 单机部署仅需 1 个可执行文件,5 分钟内即可完成环境搭建。

  4. 数据备份场景:企业核心业务数据需异地备份,MinIO 支持跨节点数据同步与多副本存储,保障数据冗余安全。

四、Windows 环境下 MinIO 部署与配置

1. 下载 MinIO

硬件要求:Windows 7 及以上 64 位系统,建议 CPU 2 核及以上、内存 4GB 及以上,存储盘预留至少 10GB 可用空间(用于存储服务数据)。

软件下载:(推荐方式二)

  • 方式一:访问 MinIO 官方下载页(https://min.io/download)(太慢了),
    下载核心服务端程序 minio.exe;若需命令行管理工具,可同步下载客户端 mc.exe(可选)。
    在这里插入图片描述
  • 方式二:访问 MinIO 国内镜像地址(https://www.minio.org.cn/)(速度飞起)
    下载核心服务端程序 minio.exe;若需命令行管理工具,可同步下载客户端 mc.exe(可选)。
    在这里插入图片描述

2. 启动 MinIO

(1)规划目录

首先在本地磁盘(建议非系统盘,如 D 盘)创建标准化目录结构,用于统一管理程序与数据:
以下是我存放的位置(你们可以根据情况自行更改)

  • 主目录:D:\Develop\Env\MinIO(存放部署相关文件)
  • 程序目录:D:\Develop\Env\MinIO\bin(存放 minio.exemc.exe 等可执行文件)
  • 数据目录:D:\Develop\Env\MinIO\data(用于存储 MinIO 管理的对象数据,避免临时目录导致数据丢失)
  • 日志目录:D:\Develop\Env\MinIO\logs(用于存储服务启动日志,便于问题排查)

在这里插入图片描述

在这里插入图片描述
(2)创建启动脚本
创建一个txt文件,然后复制下面的命令(脚本中的位置根据你的存放的位置自行修改),在改成bat后缀

@echo off
:: 切换编码为 UTF-8,避免中文乱码
chcp 65001 > nul
echo 正在启动MinIO服务...
:: 切换至程序目录
cd D:\Develop\Env\MinIO\bin
:: 启动服务,指定数据目录、控制台端口
minio.exe server D:\Develop\Env\MinIO\data --console-address ":9001"
pause

然后放到 和 bin 目录同级别

在这里插入图片描述

(3)双击启动

在这里插入图片描述
访问 http://127.0.0.1:9001,用户名和密码默认都为 minioadmin
在这里插入图片描述
在这里插入图片描述

3. 汉化操作

目前没有汉化配置。有的话也是和源码相关的(忒麻烦),所以最快的方式就是浏览器翻译
在这里插入图片描述
在这里插入图片描述

4. MinIO 核心概念解析

  1. 桶(Bucket):MinIO 的基本存储单元,用于对对象进行分类管理,类似文件系统中的 “文件夹”,但无层级嵌套限制(可通过对象名中的 “/” 模拟层级)。
    命名规则:3-63 个字符,仅支持小写字母、数字、横线,且不能以横线开头或结尾。

  2. 对象(Object):MinIO 中存储的核心数据单元,对应实际的文件(如图片、文档),由 “文件内容 + 元数据” 组成。
    元数据包含文件大小、类型、创建时间等基础信息,支持自定义扩展(如给文件添加业务标签)。

  3. API 服务端口:默认 9000 端口,用于客户端(如 Spring Boot 应用)通过 SDK 集成 MinIO,实现文件上传、下载等自动化操作。

  4. Web 控制台端口:默认 9001 端口,提供可视化管理界面,支持手动创建桶、上传文件、配置权限等操作。

5. MinIO 基础操作指南(Web 控制台)

(1)创建存储桶

登录 Web 控制台后,点击左侧菜单栏 “Create Bucket”。输入桶名称(如 test-123

在这里插入图片描述
在这里插入图片描述

你可以看看data下面,就出现了你创建的那个桶了

在这里插入图片描述

(2)对象操作—桶下面创建文件夹

前提是你创建文件夹以后,还得再到这个新文件夹里面上传一个资源才行,不然就属于无效

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(3)对象操作—桶下面创建文件

在这里插入图片描述

你可以看看data下面,就出现了《API命名规范.txt》的这个文件夹

在这里插入图片描述

和windows的不一样,windows 就直接是文件了,而它是以文件夹方式的,里面还有一层,这个 xl.meta 才是《API命名规范.txt》的真正的数据

在这里插入图片描述

五、SpringBoot集成MinIO

1. 引入maven

我这边是jdk1.8 建议选择 8.5.6

<!-- MinIO 官方 Java SDK -->
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.6</version> <!-- JDK 1.8 推荐版本 -->
</dependency><!-- 用于文件流处理的工具类(可选) -->
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version>
</dependency>

2. 配置 MinIO 连接信息

在 application.yml 中配置 MinIO 连接参数:

spring:minio:endpoint: http://localhost:9000  # MinIO API 地址access-key: minioadmin          # 管理员账号secret-key: minioadmin          # 管理员密码bucket-name: test-bucket        # 默认操作的桶(提前创建)base-url: http://localhost:9000/test-bucket/  # 公开桶的文件访问基础路径

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 {// 从配置文件读取 MinIO 连接参数@Value("${spring.minio.endpoint}")private String endpoint;@Value("${spring.minio.access-key}")private String accessKey;@Value("${spring.minio.secret-key}")private String secretKey;/*** 初始化 MinIO 客户端,交给 Spring 容器管理* @return MinioClient 实例*/@Beanpublic MinioClient minioClient() {return MinioClient.builder().endpoint(endpoint)  // 设置 API 地址.credentials(accessKey, secretKey)  // 设置账号密码.build();}
}

4. 封装 MinIO 工具类

import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.concurrent.TimeUnit;@Component
public class MinioUtil {@Autowiredprivate MinioClient minioClient;@Value("${spring.minio.bucket-name}")private String defaultBucket;  // 默认桶名@Value("${spring.minio.base-url}")private String baseUrl;        // 公开桶的文件访问基础路径/*** 创建桶(如果桶不存在)* @param bucketName 桶名* @throws Exception 异常*/public void createBucket(String bucketName) throws Exception {// 判断桶是否存在if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {// 不存在则创建桶minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());}}/*** 上传文件(支持 MultipartFile 类型,Spring 接收前端文件的标准类型)* @param file 前端上传的文件* @param bucketName 桶名(可为空,使用默认桶)* @return 文件访问路径* @throws Exception 异常*/public String uploadFile(MultipartFile file, String bucketName) throws Exception {// 若未指定桶名,使用默认桶if (bucketName == null || bucketName.isEmpty()) {bucketName = defaultBucket;}// 确保桶存在createBucket(bucketName);// 生成唯一文件名(前缀+时间戳+原文件名,避免重复)String originalFilename = file.getOriginalFilename();String fileName = "upload/" + System.currentTimeMillis() + "_" + originalFilename;// 上传文件到 MinIOminioClient.putObject(PutObjectArgs.builder().bucket(bucketName)  // 桶名.object(fileName)   // 存储在 MinIO 中的文件名(可包含路径,如 "img/123.jpg")// 文件流(MultipartFile 的输入流).stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType())  // 文件类型(如 image/jpeg).build());// 返回文件访问路径(公开桶可直接访问)return baseUrl + fileName;}/*** 下载文件(返回文件输入流,用于前端下载)* @param fileName 文件名(与上传时的 fileName 一致)* @param bucketName 桶名(可为空,使用默认桶)* @return 文件输入流* @throws Exception 异常*/public InputStream downloadFile(String fileName, String bucketName) throws Exception {if (bucketName == null || bucketName.isEmpty()) {bucketName = defaultBucket;}// 获取文件输入流return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());}/*** 删除文件* @param fileName 文件名* @param bucketName 桶名(可为空,使用默认桶)* @throws Exception 异常*/public void deleteFile(String fileName, String bucketName) throws Exception {if (bucketName == null || bucketName.isEmpty()) {bucketName = defaultBucket;}// 删除文件minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());}/*** 获取桶列表* @return 桶列表* @throws Exception 异常*/public List<Bucket> getBucketList() throws Exception {return minioClient.listBuckets();}/*** 获取私有文件的临时访问链接(适用于私有桶,链接有有效期)* @param fileName 文件名* @param bucketName 桶名(可为空,使用默认桶)* @param expireSeconds 链接有效期(秒)* @return 临时访问链接* @throws Exception 异常*/public String getPresignedUrl(String fileName, String bucketName, int expireSeconds) throws Exception {if (bucketName == null || bucketName.isEmpty()) {bucketName = defaultBucket;}// 生成临时访问链接return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET)  // 请求方法.bucket(bucketName).object(fileName).expiry(expireSeconds, TimeUnit.SECONDS)  // 链接有效期.build());}
}

5. 编写测试接口

import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.InputStream;@RestController
@RequestMapping("/minio")
public class MinioController {@Autowiredprivate MinioUtil minioUtil;/*** 测试上传文件* @param file 前端上传的文件(form-data 格式)* @return 文件访问路径*/@PostMapping("/upload")public String uploadFile(@RequestParam("file") MultipartFile file) {try {// 上传到默认桶,返回文件访问路径return minioUtil.uploadFile(file, null);} catch (Exception e) {return "上传失败:" + e.getMessage();}}/*** 测试下载文件* @param fileName 文件名(与上传时返回的路径中的文件名部分一致)* @return 响应实体(文件字节流)*/@GetMapping("/download")public ResponseEntity<byte[]> downloadFile(@RequestParam("fileName") String fileName) {try {// 获取文件输入流InputStream in = minioUtil.downloadFile(fileName, null);// 转换为字节数组byte[] bytes = IOUtils.toByteArray(in);// 设置响应头(解决中文文件名乱码)HttpHeaders headers = new HttpHeaders();headers.setContentDispositionFormData("attachment", new String(fileName.getBytes("UTF-8"), "ISO-8859-1"));headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);// 返回文件字节流return new ResponseEntity<>(bytes, headers, HttpStatus.OK);} catch (Exception e) {return ResponseEntity.status(500).body(("下载失败:" + e.getMessage()).getBytes());}}/*** 测试删除文件* @param fileName 文件名* @return 操作结果*/@DeleteMapping("/delete")public String deleteFile(@RequestParam("fileName") String fileName) {try {// 删除文件minioUtil.deleteFile(fileName, null);return "删除成功";} catch (Exception e) {return "删除失败:" + e.getMessage();}}/*** 测试获取私有文件的临时访问链接* @param fileName 文件名* @return 临时访问链接(有效期 1 小时)*/@GetMapping("/getUrl")public String getFileUrl(@RequestParam("fileName") String fileName) {try {// 获取临时链接,有效期 3600 秒(1 小时)return minioUtil.getPresignedUrl(fileName, null, 3600);} catch (Exception e) {return "获取链接失败:" + e.getMessage();}}
}

6. 测试验证

  1. 启动 SpringBoot 项目和 MinIO 服务。
  2. 使用 Postman 测试接口:
    • 上传文件:发送 POST 请求到 http://localhost:8080/minio/upload,参数类型 form-data,键 file,值选择本地文件,返回文件访问路径。
    • 下载文件:发送 GET 请求到 http://localhost:8080/minio/download?fileName=上传返回的文件名,浏览器自动下载文件。
    • 删除文件:发送 DELETE 请求到 http://localhost:8080/minio/delete?fileName=文件名,返回删除结果。
    • 获取临时链接:发送 GET 请求到 http://localhost:8080/minio/getUrl?fileName=文件名,返回有效期 1 小时的临时访问链接。
http://www.dtcms.com/a/605104.html

相关文章:

  • 【开题答辩全过程】以 基于.NET MVC的线上鞋服交易系统设计与实现为例,包含答辩的问题和答案
  • MySQL 全体系深度解析(存储引擎、事务、日志、MVCC、锁、索引、执行计划、复制、调优)
  • SpringMVC基础教程(1)--MVC/DispathcerServlet
  • 在streampark运行paimon-flink-action-1.20.0.jar
  • AI得贤面试智能体:重构企业招聘新范式
  • 硅基计划6.0 陆 JavaEE HttpHttps协议
  • 稳定边界层高度参数化方案的回归建模
  • 企业网站推广方法wap网站预览
  • 可以做推广的门户网站wordpress适合中国的小插件介绍
  • Dubbo服务治理全解析:从零搭建高可用微服务架构
  • java List怎么转换为Vector
  • 2023年辽宁省数学建模竞赛-B题 数据驱动的水下导航适配区分类预测-基于支持向量机对水下导航适配区分类的研究
  • 机器学习--KNN算法中的距离、范数、正则化
  • openGauss向量数据库功能实操测评:轻量部署下的高维检索能力
  • php做网站还是linuxseo服务外包费用
  • 《算法通关指南:算法基础篇 ---- 二维前缀和 — 1. 【模板】二维度前缀和,2.激光炸弹》
  • SpringBoot+openGauss DataVec构建高效RAG知识库实践
  • JVM 垃圾回收算法的详细介绍
  • 生成式引擎优化(GEO)实用指南(三):结构化内容与AI优化策略
  • 114啦怎么建设网站怎么样推广自己的公司
  • 可视化图标开发“懂一点”|数据可视化术语表
  • SpringMVC(1)学习
  • 高频Linux 面试题
  • 芜湖效能建设网站重庆发布公众号
  • Spring Boot 多环境配置详解:Maven Profile vs 启动参数注入
  • 《Chart.js 饼图:高效与灵活的数据可视化工具详解》
  • 力扣每日刷题251113
  • erp网站开发网站后台管理系统源码下载
  • Spring IOC核心原理与实战技巧
  • 计算中央子午线(Excel版)