SpringBoot与Minio的极速之旅:解锁文件切片上传新境界

2024-09-06 03:36

本文主要是介绍SpringBoot与Minio的极速之旅:解锁文件切片上传新境界,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

一、前言

二、对象存储(Object Storage)介绍

(1)对象存储的特点

(2)Minio 与对象存储

(3)对象存储其他存储方式的区别

(4)对象存储的应用场景

三、Minio基础介绍

(1)主要特性

(2)应用场景

(3)架构和部署

四、SringBoot集成MinIO实现切片上传

1. 引入依赖

2.配置MinIO相关配置信息

3. 配置 MinIO 客户端

4. 创建文件切片上传服务

5. 创建文件切片上传控制器

6.测试及说明


一、前言

在数字化时代,文件上传是众多应用不可或缺的一环。随着文件体积的增大和用户对上传速度的追求,传统的上传方式已难以满足需求。SpringBoot作为Java开发者的利器,结合Minio这一高性能对象存储解决方案,为我们提供了一种全新的文件上传体验——文件切片极速上传。

本文将带领读者深入探索SpringBoot与Minio的结合,通过文件切片技术,实现高效、稳定的文件上传。我们将从基础概念出发,逐步介绍这个文件切片上传系统,解锁上传速度的新境界。希望对正在研究文件存储的小伙伴们有所启发~

二、对象存储(Object Storage)介绍

首先简单介绍一下对象存储的相关概念~~~

对象存储是一种数据存储架构,它将数据作为对象进行管理,而不是传统的文件系统或块存储方式。每个对象通常包含数据本身、元数据和唯一标识符。对象存储适用于大规模数据存储和高并发访问场景,具有高扩展性、高可靠性和低成本的特点。

(1)对象存储的特点

  1. 高扩展性

    • 对象存储系统可以轻松扩展存储容量,通过增加存储节点来满足不断增长的数据需求。

  2. 高可靠性

    • 对象存储系统通常采用数据冗余和分布式存储技术,确保数据的高可用性和可靠性。即使部分节点故障,数据也不会丢失。

  3. 低成本

    • 对象存储采用廉价的存储介质(如硬盘),并通过数据压缩和去重技术减少存储空间的占用,从而降低存储成本。

  4. 丰富的元数据

    • 每个对象都包含丰富的元数据,可以用于描述数据的属性、访问权限等信息,方便数据的检索和管理。

  5. RESTful API

    • 对象存储系统通常提供 RESTful API,方便开发者通过 HTTP 协议进行数据的上传、下载和管理。

(2)Minio 与对象存储

Minio 是一个典型的对象存储解决方案,它完全兼容 Amazon S3 API,提供了以下对象存储的核心功能:

  1. 对象管理

    • Minio 将数据作为对象进行管理,每个对象包含数据本身、元数据和唯一标识符。用户可以通过 S3 API 进行对象的创建、读取、更新和删除操作。

  2. 存储桶(Bucket)

    • 存储桶是对象的容器,类似于文件系统中的目录。用户可以在 Minio 中创建和管理多个存储桶,每个存储桶可以包含多个对象。

  3. 访问控制

    • Minio 支持基于存储桶和对象的访问控制,用户可以通过策略(Policy)和访问控制列表(ACL)来管理数据的访问权限。

  4. 数据冗余

    • Minio 支持分布式部署,通过数据冗余技术确保数据的高可用性和可靠性。分布式 Minio 可以自动处理数据复制和故障恢复。

  5. 数据加密

    • Minio 支持数据加密,包括服务器端加密和客户端加密,确保数据在传输和存储过程中的安全性。

  6. RESTful API

    • Minio 提供 RESTful API,方便开发者通过 HTTP 协议进行数据的管理和访问。

(3)对象存储其他存储方式的区别

对象存储(Object Storage)和普通存储(包括文件存储和块存储)是三种不同的数据存储架构,它们在数据管理方式、扩展性、性能和应用场景等方面存在显著差异。

存储方式数据管理方式扩展性性能应用场景优点缺点
对象存储数据作为对象进行管理,每个对象包含数据本身、元数据和唯一标识符。对象存储通常提供 RESTful API 进行数据访问和管理。具有极高的扩展性,可以通过增加存储节点来扩展存储容量和提高性能。适用于大规模数据访问和高并发场景,具有较高的吞吐量和较低的延迟。适用于大规模数据存储和高并发访问场景,如静态网站托管、大数据处理、备份和归档、云原生应用等。

高扩展性:可以轻松扩展存储容量和性能;

高可靠性:通过数据冗余和分布式存储确保数据的高可用性和可靠性;

低成本:采用廉价的存储介质,并通过数据压缩和去重技术降低存储成本;

丰富的元数据:每个对象包含丰富的元数据,方便数据的检索和管理;

RESTful API:提供 RESTful API,方便开发者进行数据访问和管理。

延迟较高:相对于块存储,对象存储的延迟较高,不适用于对延迟要求极高的应用场景。

复杂性:对象存储的架构和管理相对复杂,需要专业的技术团队进行维护。

文件存储数据作为文件和目录层次结构进行管理,类似于传统的文件系统。文件存储通常提供文件路径进行数据访问。扩展性有限,通常受限于单个服务器的存储容量和性能。适用于中小规模数据访问,性能受限于单个服务器的处理能力。适用于文件共享和协作场景,如企业文件服务器、网络附加存储(NAS)等。

简单易用:文件存储的架构和管理相对简单,易于使用和维护。

兼容性:兼容传统的文件系统操作,方便用户进行数据访问和管理。

扩展性有限:受限于单个服务器的存储容量和性能,难以扩展。

性能有限:性能受限于单个服务器的处理能力,不适用于高并发和大规模数据访问场景。

块存储数据作为固定大小的块进行管理,每个块具有唯一的标识符。块存储通常作为虚拟机的存储卷使用,提供低延迟的数据访问。扩展性一般,通常通过增加存储设备或扩展存储区域网络(SAN)来提高存储容量。提供低延迟的数据访问,适用于对性能要求较高的应用场景,如数据库和虚拟机。适用于对性能要求较高的应用场景,如数据库、虚拟化环境、高性能计算等。

低延迟:提供低延迟的数据访问,适用于对性能要求较高的应用场景。

高性能:适用于数据库、虚拟化环境等高性能计算场景。

扩展性有限:通常通过增加存储设备或扩展存储区域网络(SAN)来提高存储容量,扩展性有限。

成本较高:相对于对象存储,块存储的成本较高,特别是在大规模存储场景下。

(4)对象存储的应用场景

对象存储适用于多种应用场景,包括但不限于:

  • 静态网站托管:对象存储可以作为静态网站的存储和分发平台,提供高速的内容传输。

  • 大数据处理:对象存储可以作为大数据处理框架(如 Hadoop、Spark)的存储后端,提供高效的数据访问。

  • 备份和归档:对象存储可以用于企业数据的备份和归档,确保数据的安全性和可恢复性。

  • 云原生应用:对象存储与 Kubernetes 等容器编排平台无缝集成,适用于云原生应用的存储需求。

三、Minio基础介绍

Minio 是一个开源的高性能对象存储解决方案,专为云原生应用设计。它兼容 Amazon S3 API,提供了简单、可靠的存储服务,适用于各种规模的应用场景。Minio 的设计理念是轻量级和高性能,使其成为容器化和微服务架构中的理想选择。

(1)主要特性

  1. 兼容 S3 API

    • Minio 完全兼容 Amazon S3 API,这意味着开发者可以使用现有的 S3 客户端和工具与 Minio 进行交互,无需修改代码。

  2. 分布式存储

    • Minio 支持分布式部署,可以通过扩展节点来增加存储容量和提高性能。分布式 Minio 可以自动处理数据冗余和故障恢复,确保数据的高可用性和可靠性。

  3. 高性能

    • Minio 采用 Go 语言编写,具有出色的性能和低延迟。它能够处理大规模的数据传输,适用于高并发场景。

  4. 数据安全

    • Minio 支持数据加密(包括服务器端加密和客户端加密),确保数据在传输和存储过程中的安全性。

  5. 简单易用

    • Minio 的安装和配置非常简单,支持多种操作系统和平台。它还提供了丰富的管理工具和 API,方便开发者进行管理和监控。

  6. 开源免费

    • Minio 是开源项目,采用 Apache License 2.0 许可,用户可以免费使用并对其进行二次开发。

(2)应用场景

Minio 适用于多种应用场景,包括但不限于:

  • 静态网站托管:Minio 可以作为静态网站的存储和分发平台,提供高速的内容传输。

  • 大数据处理:Minio 可以作为大数据处理框架(如 Hadoop、Spark)的存储后端,提供高效的数据访问。

  • 备份和归档:Minio 可以用于企业数据的备份和归档,确保数据的安全性和可恢复性。

  • 云原生应用:Minio 与 Kubernetes 等容器编排平台无缝集成,适用于云原生应用的存储需求。

(3)架构和部署

Minio 支持单节点和分布式部署两种模式:

  • 单节点部署:适用于小规模应用和开发测试环境。单节点 Minio 部署简单,易于管理。

  • 分布式部署:适用于大规模应用和高可用性需求。分布式 Minio 通过多个节点组成存储集群,提供更高的性能和可靠性。

Minio 的部署可以通过 Docker 容器、Kubernetes 集群或直接在物理服务器上进行。它还提供了丰富的命令行工具和 Web 管理界面,方便用户进行配置和管理。这里主要介绍SpringBoot与minio的集成,因此这块笔者就不单独说明部署的详细方式了,仅采用容器化单实例服务进行。

#自定义账号密码运行容器
[root@node01 ~]# docker run -d \
> -p 9000:9000 \
> -p 9001:9001 \
> --name minio \
> -v /data/minio/data:/data \
> -e "MINIO_ROOT_USER=admin" \
> -e "MINIO_ROOT_PASSWORD=admin123" \
> swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/minio/minio:RELEASE.2024-06-13T22-53-53Z server /data --console-address ":9001"
Unable to find image 'swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/minio/minio:RELEASE.2024-06-13T22-53-53Z' locally
RELEASE.2024-06-13T22-53-53Z: Pulling from ddn-k8s/docker.io/minio/minio
d95a8f5a9b46: Pull complete 
392be19a63f6: Pull complete 
86f90f8ca150: Pull complete 
7dc3c1e5f08a: Pull complete 
1ab6ab2ba6f0: Pull complete 
6fac698163eb: Pull complete 
6a4e2f681031: Pull complete 
53a5b322abdc: Pull complete 
Digest: sha256:98fe67c08bf95945b34f8e74622976495e6c47b3e8dd2faed079ac2804b98c97
Status: Downloaded newer image for swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/minio/minio:RELEASE.2024-06-13T22-53-53Z

四、SringBoot集成MinIO实现切片上传

1. 引入依赖

首先,在你的 pom.xml 文件中引入必要的依赖,包括 minio 和其他相关依赖:

<dependency><groupId>io.minio</groupId><artifactId>minio</artifactId><version>8.5.7</version>
</dependency>
<dependency><groupId>commons-fileupload</groupId><artifactId>commons-fileupload</artifactId><version>1.5</version>
</dependency>
<dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version>
</dependency>

2.配置MinIO相关配置信息

首先需要在MinIO服务页面配置一个令牌桶(Bucket),MinIO使用bucket来组织对象。bucket类似于文件系统中的文件夹或目录,其中每个bucket可以容纳任意数量的对象。这里咱们创建一个名为test的bucket。

  • versioning(版本控制):允许在同一键下保持同一对象的多个版本。

  • Object Locking(对象锁定):防止对象被删除。需要支持保留和合法持有。只能在创建桶时启用。

  • Quota(配额):限制bucket中的数据量。

  • Retention(存放):开启会施加规则,在一段时间内防止对象删除。为了设置桶保留策略,必须启用版本控制。

然后需要创建API的访问凭证,这个用于minio在springboot配置文件中使用时的配置。

完成后保留好access key和secret key信息。接下来可以在springboot的yml配置文件中配置minio的相关信息了:

server:port: 8919
spring:servlet:multipart:enabled: truemax-file-size: 2048MBmax-request-size: 2048MBconfig:file-server:#文件服务,local/minio,local本地文件服务,minio minio服务type: miniolocal:secret: e9eaa184ac1b4068829edb4f3ea978f4# 防盗链st有效时长(秒)st-effective-time: 300file-dir: D:/springboot-test/uploadFilepreview-url: http://127.0.0.1:8918minio:access-key: ZTsent9wl6UlKBGiNoaDsecret-key: b1CXhMIovbevJ2q9LQuPR4lhaFNCqSlX2o5EgQtWurl: http://192.168.1.201:9000bucket-name: test
  • access-keysecret-key是访问minio服务的凭证,就是上面刚创建的。

  • url是minio服务的地址,这里要区分web端的访问地址9001,默认9000是mino的服务地址。

  • bucket-name是存储文件的桶名,这个咱们生成的名称是test。

3. 配置 MinIO 客户端

在你的 SpringBoot 应用中配置 MinIO 客户端。可以通过创建一个配置类来实现:

package com.yy.fs.config;
​
import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
​
/*** Minio 配置** @author young* @date 2024/09/03*/
@Configuration
@Data
@ConfigurationProperties("config.file-server.minio")
public class MinioConfig {private String accessKey;private String secretKey;private String url;private String bucketName;
​@Beanpublic MinioClient minioClient() {return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();}
}

4. 创建文件切片上传服务

创建一个服务类来处理文件切片上传的逻辑:

package com.yy.fs.mytest;
​
import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.errors.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
​
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;
​
@Service
public class FileUploadService {
​private static final Logger LOGGER = LoggerFactory.getLogger(FileUploadService.class);@Autowiredprivate MinioClient minioClient;
​/** uploadChunk 用于上传文件块,参数包括桶名、对象名和文件块。*/public void uploadChunk(String bucketName, String objectName,  MultipartFile chunkFile) throws IOException, ServerException, InsufficientDataException, ErrorResponseException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {// 检查指定的桶是否存在,如果不存在则创建一个新的桶。boolean isExist =minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());if (!isExist) {// Make a new bucket called bucket.minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());} else {LOGGER.info("Bucket " + bucketName + " already exists.");}byte[] bytes = chunkFile.getBytes();ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
​String suffix = objectName.contains(".") ? objectName.substring(objectName.lastIndexOf(".")):"";// 使用MinIO客户端上传文件块到指定的桶和对象名minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName.substring(0,objectName.lastIndexOf(".")) + "_chunk"  + suffix).stream(byteArrayInputStream, byteArrayInputStream.available(), -1).build());}
}

5. 创建文件切片上传控制器

创建一个控制器来处理文件切片上传的请求,在实际项目中根据前端的参数传入即可:

package com.yy.fs.mytest;
​
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
​
@RestController
public class FileUploadController {
​@Autowiredprivate FileUploadService fileUploadService;
​@PostMapping("/uploadChunk")public String uploadChunk(@RequestParam("bucketName") String bucketName,@RequestParam("objectName") String objectName,@RequestParam("chunkFile") MultipartFile chunkFile) {try {fileUploadService.uploadChunk(bucketName, objectName,  chunkFile);return "Chunk  uploaded successfully";} catch (Exception e) {e.printStackTrace();return "Failed to upload chunk ";}}
}

6.测试及说明

最后使用测试工具测试一下,这里咱们上传一个视频文件进行测试:

上传成功后可以在MinIO界面查看到已上传的视频信息:

并且支持下载,预览与分享,基本算一个文件存储系统类似的玩意。但是实际在服务存储的目录下就不同了:

data目录下随着我们创建一个test的桶而生成了一个test文件,当文件通过后端接口传入minio后根据文件大小自动被切片为了很多小文件,这也难怪他的文件上传速度要比直接上传整个文件高效多了。更主要的是可以省略去构建切片方法实现切片逻辑的步骤,让minio自己完成。感兴趣的小伙伴可参考下方链接继续研究一下~

参考地址:MinIO中文文档

这篇关于SpringBoot与Minio的极速之旅:解锁文件切片上传新境界的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1140882

相关文章

Spring MVC如何设置响应

《SpringMVC如何设置响应》本文介绍了如何在Spring框架中设置响应,并通过不同的注解返回静态页面、HTML片段和JSON数据,此外,还讲解了如何设置响应的状态码和Header... 目录1. 返回静态页面1.1 Spring 默认扫描路径1.2 @RestController2. 返回 html2

Spring常见错误之Web嵌套对象校验失效解决办法

《Spring常见错误之Web嵌套对象校验失效解决办法》:本文主要介绍Spring常见错误之Web嵌套对象校验失效解决的相关资料,通过在Phone对象上添加@Valid注解,问题得以解决,需要的朋... 目录问题复现案例解析问题修正总结  问题复现当开发一个学籍管理系统时,我们会提供了一个 API 接口去

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

Spring核心思想之浅谈IoC容器与依赖倒置(DI)

《Spring核心思想之浅谈IoC容器与依赖倒置(DI)》文章介绍了Spring的IoC和DI机制,以及MyBatis的动态代理,通过注解和反射,Spring能够自动管理对象的创建和依赖注入,而MyB... 目录一、控制反转 IoC二、依赖倒置 DI1. 详细概念2. Spring 中 DI 的实现原理三、

SpringBoot 整合 Grizzly的过程

《SpringBoot整合Grizzly的过程》Grizzly是一个高性能的、异步的、非阻塞的HTTP服务器框架,它可以与SpringBoot一起提供比传统的Tomcat或Jet... 目录为什么选择 Grizzly?Spring Boot + Grizzly 整合的优势添加依赖自定义 Grizzly 作为

Java后端接口中提取请求头中的Cookie和Token的方法

《Java后端接口中提取请求头中的Cookie和Token的方法》在现代Web开发中,HTTP请求头(Header)是客户端与服务器之间传递信息的重要方式之一,本文将详细介绍如何在Java后端(以Sp... 目录引言1. 背景1.1 什么是 HTTP 请求头?1.2 为什么需要提取请求头?2. 使用 Spr

Java如何通过反射机制获取数据类对象的属性及方法

《Java如何通过反射机制获取数据类对象的属性及方法》文章介绍了如何使用Java反射机制获取类对象的所有属性及其对应的get、set方法,以及如何通过反射机制实现类对象的实例化,感兴趣的朋友跟随小编一... 目录一、通过反射机制获取类对象的所有属性以及相应的get、set方法1.遍历类对象的所有属性2.获取

Java中的Opencv简介与开发环境部署方法

《Java中的Opencv简介与开发环境部署方法》OpenCV是一个开源的计算机视觉和图像处理库,提供了丰富的图像处理算法和工具,它支持多种图像处理和计算机视觉算法,可以用于物体识别与跟踪、图像分割与... 目录1.Opencv简介Opencv的应用2.Java使用OpenCV进行图像操作opencv安装j

java Stream操作转换方法

《javaStream操作转换方法》文章总结了Java8中流(Stream)API的多种常用方法,包括创建流、过滤、遍历、分组、排序、去重、查找、匹配、转换、归约、打印日志、最大最小值、统计、连接、... 目录流创建1、list 转 map2、filter()过滤3、foreach遍历4、groupingB

SpringBoot如何使用TraceId日志链路追踪

《SpringBoot如何使用TraceId日志链路追踪》文章介绍了如何使用TraceId进行日志链路追踪,通过在日志中添加TraceId关键字,可以将同一次业务调用链上的日志串起来,本文通过实例代码... 目录项目场景:实现步骤1、pom.XML 依赖2、整合logback,打印日志,logback-sp