在 Spring Boot 中集成 MinIO 对象存储
作者:编码行者
MinIO 是一个开源的对象存储服务器,专注于高性能、分布式和兼容S3 API的存储解决方案。本文将介绍如何在 Spring Boot 应用程序中集成 MinIO,以便您可以轻松地将对象存储集成到您的应用中。
安装minio
1.拉取 minio Docker镜像
docker pull minio/minio
2.创建minio数据和配置目录
mkdir -p /data/minio/data /data/minio/config
3.运行minio容器,设置访问和密钥并挂载数据卷
docker run -p 9090:9090 -p 9000:9000 --name minio \ -v ~/data/minio/data:/data \ -v ~/data/minio/config:/root/.minio \ -e "MINIO_ACCESS_KEY=minio" \ -e "MINIO_SECRET_KEY=minio123" \ minio/minio server /data --console-address ":9090"
或者 使用 docker-compose.yml
version: '3.9' services: minio: command: 'server /data --console-address ":9090"' image: minio/minio environment: - MINIO_SECRET_KEY=minio123 - MINIO_ACCESS_KEY=minio volumes: - '~/data/minio/config:/root/.minio' - '~/data/minio/data:/data' container_name: minio ports: - '9000:9000' - '9090:9090'
mkdir``~/minio/data
在您的主目录中创建一个新的本地目录。
docker run
启动 MinIO 容器。
-p
将本地端口绑定到容器端口。-name
为容器创建一个名称。-v
将文件路径设置为容器要使用的持久卷位置。- 当 MinIO 将数据写入 时
/data
,该数据会镜像到本地路径~/minio/data
,从而允许其在容器重新启动之间保留。您可以替换~/minio/data
为用户具有读取、写入和删除访问权限的另一个本地文件位置。 -e
分别设置环境变量MINIO_ROOT_USER
和MINIO_ROOT_PASSWORD
。这些设置root 用户凭据。更改用于您的容器的示例值。
运行结果
WARNING: MINIO_ACCESS_KEY and MINIO_SECRET_KEY are deprecated.
Please use MINIO_ROOT_USER and MINIO_ROOT_PASSWORD
Formatting 1st pool, 1 set(s), 1 drives per set.
WARNING: Host local has more than 0 drives of set. A host failure will result in data becoming unavailable.
MinIO Object Storage Server
Copyright: 2015-2023 MinIO, Inc.
License: GNU AGPLv3 <https://www.gnu.org/licenses/agpl-3.0.html>
Version: RELEASE.2023-08-29T23-07-35Z (go1.19.12 linux/amd64)
Status: 1 Online, 0 Offline.
S3-API: http://172.17.0.2:9000 http://127.0.0.1:9000
Console: http://172.17.0.2:9090 http://127.0.0.1:9090
Documentation: https://min.io/docs/minio/linux/index.html
Warning: The standard parity is set to 0. This can lead to data loss.
4.登录 控制台 http://127.0.0.1:9090/browser 用户名密码是你启动时初始化的这里是 minio、minio123
5.创建 桶(Buckets)
参考:
https://min.io/docs/minio/container/index.html
Spring Boot 集成
1. 添加 MinIO 客户端依赖
在您的 Spring Boot 项目的 pom.xml
文件中添加 MinIO 客户端依赖:
<dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.5.5</version> </dependency>
接下来,您需要在您的Spring Boot应用程序中配置MinIO客户端。您可以在 application.properties
或 application.yml
文件中添加以下配置:
# MinIO配置 minio.endpoint=http://localhost:9000 # MinIO服务器的地址 minio.access-key=minio # 您的访问密钥 minio.secret-key=minio123 # 您的秘密密钥
2. 创建 MinIO 配置类
创建一个配置类,用于初始化 MinIO 客户端。创建一个名为 MinioConfig
的类:
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.access-key}") private String accessKey; @Value("${minio.secret-key}") private String secretKey; @Bean public MinioClient minioClient() { return MinioClient.builder() .endpoint(endpoint) .credentials(accessKey, secretKey) .build(); } }
3. 集成 MinIO 操作到您的应用
您可以在您的服务或控制器中使用 MinioClient
来进行 MinIO 操作。以下是一个上传文件到 MinIO 的示例:
import io.minio.GetObjectArgs; import io.minio.GetObjectResponse; import io.minio.MinioClient; import io.minio.PutObjectArgs; import okhttp3.Headers; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.InputStreamResource; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.HashMap; import java.util.Map; import java.util.Optional; import java.util.UUID; @RestController @RequestMapping("/minio") public class MinioController { @Autowired private MinioClient minioClient; @PostMapping("/upload") public String uploadFile(@RequestParam("file") MultipartFile file) { try { /** * 使用 UUID 作为对象名称: * 1. 唯一性,避免对象名称冲突。 * 2. 隐藏实际文件信息,提高一定的隐私。 * 3. 对象名称不受原始文件名长度或特殊字符的限制。 * 在实际场景中,如果你更注重文件的可识别性和管理,可以考虑使用文件名称。如果你更注重唯一性和隐私性,可以考虑使用 UUID。 * 同时,你也可以结合两者,例如将文件名作为对象属性存储,然后使用 UUID 作为对象名称。这样既可以保留文件信息,又能保证唯一性。 */ String objectName = UUID.randomUUID().toString(); Map<String, String> metadata = new HashMap<>(); metadata.put("originalFilename", file.getOriginalFilename()); minioClient.putObject( PutObjectArgs.builder() .bucket("firsttest") .object(objectName) .userMetadata(metadata) .stream(file.getInputStream(), file.getSize(), -1) .contentType(file.getContentType()) .build() ); return "File uploaded successfully! fileId: " + objectName; } catch (Exception e) { return "Error uploading file: " + e.getMessage(); } } @GetMapping("/download/{filename}") public ResponseEntity<InputStreamResource> downloadFile(@PathVariable("filename") String filename) { try { Optional<GetObjectResponse> inputStream = Optional.ofNullable(minioClient.getObject( GetObjectArgs.builder() .bucket("firsttest") .object(filename) .build() )); if (inputStream.isPresent()) { InputStreamResource resource = new InputStreamResource(inputStream.get()); Headers headers = inputStream.get().headers(); ResponseEntity.BodyBuilder bodyBuilder = ResponseEntity.ok(); String mediaType = headers.get("Content-Type"); if (StringUtils.isNotEmpty(mediaType)) { bodyBuilder.contentType(MediaType.parseMediaType(mediaType)); } return bodyBuilder.header("Content-Disposition", "attachment; filename=" + URLEncoder.encode(headers.get("X-Amz-Meta-originalfilename"), StandardCharsets.UTF_8)) .body(resource); } else { return ResponseEntity.notFound().build(); } } catch (Exception e) { return ResponseEntity.badRequest().body(null); } } }
使用 UUID 作为对象名称:
- 唯一性,避免对象名称冲突。
- 隐藏实际文件信息,提高一定的隐私。
- 对象名称不受原始文件名长度或特殊字符的限制。
在实际场景中,如果你更注重文件的可识别性和管理,可以考虑使用文件名称。如果你更注重唯一性和隐私性,可以考虑使用 UUID。同时,你也可以结合两者,例如将文件名作为对象属性存储,然后使用 UUID 作为对象名称。这样既可以保留文件信息,又能保证唯一性。
http://127.0.0.1:80/minio/upload
上传完毕成功后,控制台查看文件
自定义 metadata 为啥前缀有 X-Amz-Meta-?
在 MinIO 中,当你设置自定义元数据(metadata)时,MinIO 会遵循 Amazon S3 的元数据规范,其中元数据的键名> 前会添加
x-amz-meta-
前缀。这是因为 MinIO 是一个兼容 Amazon S3 API 的对象存储服务器,因此它采用了 Amazon > S3 的一些规范和约定。Amazon S3 使用
x-amz-meta-
前缀来标识用户自定义的元数据,以便与 Amazon S3 内部使用的标准元数据进行区> 分。这样可以确保用户自定义的元数据不会与 S3 内部使用的元数据冲突。这也是为了保持兼容性,使 MinIO 用户可以> 使用与 Amazon S3 相同的元数据命名约定。因此,在 MinIO 中设置自定义元数据时,不需要手动添加
x-amz-meta-
前缀,MinIO 会自动处理这个前缀,确保它符合 Amazon S3 的规范。当你从对象中检索元数据时,MinIO 也会自动解析并返回合适的键名,不包含前缀。总之,这个前缀是 MinIO 为了兼容 Amazon S3 API,保持统一性而引入的。
请注意,上述示例仅为基本示例,用于展示如何在Spring Boot中集成MinIO。您可以根据您的实际需求进行更多的配置和操作。确保替换示例中的"your-access-key"、“your-secret-key”、"your-bucket-name"和其他参数为您自己的值。
最后,不要忘记在您的MinIO服务器上创建对应的存储桶(Bucket),以及设置正确的访问权限。
到此这篇关于在 Spring Boot 中集成 MinIO 对象存储的文章就介绍到这了,更多相关Spring Boot集成 MinIO 对象存储内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!