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

MinIO介绍以及结合SpringBoot的应用场景详解

 

目录

什么是MinIO?

MinIO的核心特性

MinIO与传统存储的对比

1. 与传统文件系统对比

2. 与关系型数据库对比

MinIO安装和配置

1. Docker安装

2. 单机部署

3. 分布式部署

Spring Boot集成MinIO

1. Maven依赖

2. 配置文件

3. MinIO配置类

4. MinIO服务类

实际应用场景

1. 文件上传服务

2. 图片处理服务


什么是MinIO?

MinIO是一个高性能的分布式对象存储服务,兼容Amazon S3 API。它专为云原生应用设计,具有高性能、可扩展、易部署等特点。MinIO可以用于存储各种类型的数据,如图片、视频、文档、备份文件等。

MinIO的核心特性

    1. 高性能:支持高并发读写,单节点可处理数万QPS

    2. 兼容S3:完全兼容Amazon S3 API,便于迁移

    3. 分布式:支持水平扩展,可扩展到数百个节点

    4. 云原生:支持Kubernetes部署,容器化友好

    5. 安全性:支持加密、访问控制、版本控制

    6. 易部署:单二进制文件,部署简单

    7. 开源免费:Apache 2.0许可证

MinIO与传统存储的对比

1. 与传统文件系统对比
// 传统文件系统存储
public class TraditionalFileStorage {public void saveFile(String fileName, byte[] data) {// 需要管理文件路径String filePath = "/data/uploads/" + fileName;// 需要处理目录创建File directory = new File("/data/uploads");if (!directory.exists()) {directory.mkdirs();}// 需要处理文件写入try (FileOutputStream fos = new FileOutputStream(filePath)) {fos.write(data);}// 需要处理备份、同步等问题}
}// MinIO对象存储
public class MinIOStorage {public void saveFile(String fileName, byte[] data) {// 直接上传到对象存储minioClient.putObject(PutObjectArgs.builder().bucket("my-bucket").object(fileName).stream(new ByteArrayInputStream(data), data.length, -1).build());// 自动处理分布式、备份等问题}
}
2. 与关系型数据库对比
// 数据库存储文件
@Entity
public class FileEntity {@Idprivate Long id;@Lob@Column(columnDefinition = "LONGBLOB")private byte[] fileData;  // 大文件存储在数据库中private String fileName;private String contentType;private Long fileSize;
}// MinIO存储文件
public class MinIOFileService {public void uploadFile(String fileName, byte[] data) {// 文件存储在MinIO中minioClient.putObject(PutObjectArgs.builder().bucket("files").object(fileName).stream(new ByteArrayInputStream(data), data.length, -1).build());// 数据库中只存储元数据FileMetadata metadata = new FileMetadata();metadata.setFileName(fileName);metadata.setFileUrl("https://minio.example.com/files/" + fileName);metadata.setFileSize(data.length);fileMetadataRepository.save(metadata);}
}

MinIO安装和配置

1. Docker安装
# docker-compose.yml
version: '3.8'
services:minio:image: minio/minio:latestcontainer_name: minioports:- "9000:9000"      # API端口- "9001:9001"      # 控制台端口environment:MINIO_ROOT_USER: adminMINIO_ROOT_PASSWORD: admin123volumes:- minio_data:/datacommand: server /data --console-address ":9001"healthcheck:test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]interval: 30stimeout: 20sretries: 3volumes:minio_data:
2. 单机部署
# 下载MinIO
wget https://dl.min.io/server/minio/release/linux-amd64/minio
chmod +x minio# 启动MinIO
./minio server /data --console-address ":9001"
3. 分布式部署
# 4节点分布式部署
./minio server http://minio{1...4}/data --console-address ":9001"

Spring Boot集成MinIO

1. Maven依赖
<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.7</version>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2. 配置文件
# application.yml
minio:endpoint: http://localhost:9000access-key: adminsecret-key: admin123bucket: default-bucketregion: us-east-1secure: false
3. MinIO配置类
import io.minio.MinioClient;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinIOConfig {private String endpoint;private String accessKey;private String secretKey;private String bucket;private String region;private boolean secure;@Beanpublic MinioClient minioClient() {return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).region(region).build();}@Beanpublic String defaultBucket() {return bucket;}// getter和setter方法public String getEndpoint() { return endpoint; }public void setEndpoint(String endpoint) { this.endpoint = endpoint; }public String getAccessKey() { return accessKey; }public void setAccessKey(String accessKey) { this.accessKey = accessKey; }public String getSecretKey() { return secretKey; }public void setSecretKey(String secretKey) { this.secretKey = secretKey; }public String getBucket() { return bucket; }public void setBucket(String bucket) { this.bucket = bucket; }public String getRegion() { return region; }public void setRegion(String region) { this.region = region; }public boolean isSecure() { return secure; }public void setSecure(boolean secure) { this.secure = secure; }
}
4. MinIO服务类
import io.minio.*;
import io.minio.errors.*;
import io.minio.messages.Item;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;@Service
public class MinIOService {@Autowiredprivate MinioClient minioClient;@Autowiredprivate String defaultBucket;/*** 上传文件*/public String uploadFile(MultipartFile file) throws Exception {// 生成唯一文件名String fileName = generateFileName(file.getOriginalFilename());// 检查bucket是否存在,不存在则创建ensureBucketExists(defaultBucket);// 上传文件minioClient.putObject(PutObjectArgs.builder().bucket(defaultBucket).object(fileName).stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build());return fileName;}/*** 下载文件*/public InputStream downloadFile(String fileName) throws Exception {return minioClient.getObject(GetObjectArgs.builder().bucket(defaultBucket).object(fileName).build());}/*** 删除文件*/public void deleteFile(String fileName) throws Exception {minioClient.removeObject(RemoveObjectArgs.builder().bucket(defaultBucket).object(fileName).build());}/*** 获取文件列表*/public List<String> listFiles(String prefix) throws Exception {Iterable<Result<Item>> results = minioClient.listObjects(ListObjectsArgs.builder().bucket(defaultBucket).prefix(prefix).build());List<String> fileNames = new ArrayList<>();for (Result<Item> result : results) {fileNames.add(result.get().objectName());}return fileNames;}/*** 生成预签名URL(用于临时访问)*/public String getPresignedUrl(String fileName, int expirySeconds) throws Exception {return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(defaultBucket).object(fileName).expiry(expirySeconds).build());}/*** 检查bucket是否存在*/private void ensureBucketExists(String bucketName) throws Exception {boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());if (!found) {minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());}}/*** 生成唯一文件名*/private String generateFileName(String originalFileName) {String extension = "";if (originalFileName != null && originalFileName.contains(".")) {extension = originalFileName.substring(originalFileName.lastIndexOf("."));}return UUID.randomUUID().toString() + extension;}
}

实际应用场景

1. 文件上传服务
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.http.ResponseEntity;@RestController
@RequestMapping("/api/files")
public class FileController {@Autowiredprivate MinIOService minIOService;/*** 上传文件*/@PostMapping("/upload")public ResponseEntity<?> uploadFile(@RequestParam("file") MultipartFile file) {try {// 验证文件if (file.isEmpty()) {return ResponseEntity.badRequest().body("文件不能为空");}// 验证文件大小(10MB)if (file.getSize() > 10 * 1024 * 1024) {return ResponseEntity.badRequest().body("文件大小不能超过10MB");}// 验证文件类型String contentType = file.getContentType();if (contentType == null || !contentType.startsWith("image/")) {return ResponseEntity.badRequest().body("只支持图片文件");}// 上传文件String fileName = minIOService.uploadFile(file);return ResponseEntity.ok(new FileUploadResponse(fileName, "上传成功"));} catch (Exception e) {return ResponseEntity.internalServerError().body("上传失败: " + e.getMessage());}}/*** 下载文件*/@GetMapping("/download/{fileName}")public ResponseEntity<?> downloadFile(@PathVariable String fileName) {try {InputStream inputStream = minIOService.downloadFile(fileName);return ResponseEntity.ok().header("Content-Disposition", "attachment; filename=\"" + fileName + "\"").body(inputStream);} catch (Exception e) {return ResponseEntity.notFound().build();}}/*** 获取文件访问URL*/@GetMapping("/url/{fileName}")public ResponseEntity<?> getFileUrl(@PathVariable String fileName) {try {// 生成1小时有效的预签名URLString url = minIOService.getPresignedUrl(fileName, 3600);return ResponseEntity.ok(new FileUrlResponse(url));} catch (Exception e) {return ResponseEntity.internalServerError().body("获取URL失败");}}/*** 删除文件*/@DeleteMapping("/{fileName}")public ResponseEntity<?> deleteFile(@PathVariable String fileName) {try {minIOService.deleteFile(fileName);return ResponseEntity.ok("删除成功");} catch (Exception e) {return ResponseEntity.internalServerError().body("删除失败");}}
}// 响应类
class FileUploadResponse {private String fileName;private String message;public FileUploadResponse(String fileName, String message) {this.fileName = fileName;this.message = message;}// getter方法public String getFileName() { return fileName; }public String getMessage() { return message; }
}class FileUrlResponse {private String url;public FileUrlResponse(String url) {this.url = url;}public String getUrl() { return url; }
}
2. 图片处理服务(缩略图、水印)
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;@Service
public class ImageProcessingService {@Autowiredprivate MinIOService minIOService;/*** 生成缩略图*/public String generateThumbnail(String originalFileName, int width, int height) throws Exception {// 下载原图InputStream originalStream = minIOService.downloadFile(originalFileName);BufferedImage originalImage = ImageIO.read(originalStream);// 生成缩略图BufferedImage thumbnail = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics2D g = thumbnail.createGraphics();g.drawImage(originalImage, 0, 0, width, height, null);g.dispose();// 保存缩略图ByteArrayOutputStream outputStream = new ByteArrayOutputStream();ImageIO.write(thumbnail, "JPEG", outputStream);String thumbnailFileName = "thumb_" + originalFileName;minioClient.putObject(PutObjectArgs.builder().bucket(defaultBucket).object(thumbnailFileName).stream(new ByteArrayInputStream(outputStream.toByteArray()), outputStream.size(), -1).contentType("image/jpeg").build());return thumbnailFileName;}/*** 添加水印*/public String addWatermark(String originalFileName, String watermarkText) throws Exception {// 下载原图InputStream originalStream = minIOService.downloadFile(originalFileName);BufferedImage originalImage = ImageIO.read(originalStream);// 添加水印Graphics2D g = originalImage.createGraphics();g.setColor(Color.RED);g.setFont(new Font("Arial", Font.BOLD, 30));g.drawString(watermarkText, 50, 50);g.dispose();// 保存带水印的图片ByteArrayOutputStream outputStream = new ByteArrayOutputStream();ImageIO.write(originalImage, "JPEG", outputStream);String watermarkedFileName = "watermark_" + originalFileName;minioClient.putObject(PutObjectArgs.builder().bucket(defaultBucket).object(watermarkedFileName).stream(new ByteArrayInputStream(outputStream.toByteArray()), outputStream.size(), -1).contentType("image/jpeg").build());return watermarkedFileName;}
}

http://www.xdnf.cn/news/15474.html

相关文章:

  • 数据降维方法:PCA
  • 微算法科技研究量子视觉计算,利用量子力学原理提升传统计算机视觉任务的性能
  • flink sql读hive catalog数据,将string类型的时间戳数据排序后写入kafka,如何保障写入kafka的数据是有序的
  • 动态规划题解_打家劫舍【LeetCode】
  • 解决容器dns问题
  • [时序数据库-iotdb]时序数据库iotdb的安装部署
  • Go从入门到精通(25) - 一个简单web项目-实现链路跟踪
  • audiorecord 之 抢占优先级
  • 数据库询问RAG框架Vanna的总体架构
  • CMake基础:覆盖项目开发的五大配套工具
  • 数据结构——顺序表的相关操作
  • 信息学奥赛一本通 1552:【例 1】点的距离
  • 【Keil】C/C++混合编程的简单方法
  • 内存的基础相关知识,什么是内存,内存管理
  • 学习C++、QT---26(QT中实现记事本项目实现文件路径的提示、C++类模板、记事本的行高亮的操作的讲解)
  • LVS(Linux Virtual Server)详细笔记(理论篇)
  • 202507中央城市工作会议
  • 【Java】JUC并发(线程的方法、多线程的同步并发)
  • UE5多人MOBA+GAS 23、制作一个地面轰炸的技能
  • SHAP 值的数值尺度
  • 梳理Bean的创建流程
  • burpsuite使用中遇到的一些问题(bp启动后浏览器无法连接)/如何导入证书
  • GPIO 输入/输出
  • 2025年睿抗机器人开发者大赛CAIP-编程技能赛-高职组(省赛)解题报告 | 珂学家
  • 在Autodl服务器中使用VNC建立图形界面
  • 快速排序:原理、示例与 C 语言实现详解
  • C语言---自定义类型(下)(枚举和联合类型)
  • 云服务器如何管理数据库(MySQL/MongoDB)?
  • 【html常见页面布局】
  • 50天50个小项目 (Vue3 + Tailwindcss V4) ✨ | DoubleClickHeart(双击爱心)