写点什么

MinIO 对象存储——Java SDK

  • 2023-12-23
    北京
  • 本文字数:4148 字

    阅读完需:约 14 分钟

MinIO对象存储——Java SDK

系列文章:

对象存储——Minio 初探

一 MinIO SDK

对象存储——Minio 初探中我们介绍了单机部署 MinIO 的过程,以及在控制台上的一些操作。因为在实际应用中,主要还是通过 sdk 进行操作,所以这里我们也开始介绍 MinIO SDK 的使用。MinIO SDK 的官网地址https://min.io/docs/minio/linux/developers/minio-drivers.html?ref=docs。从中可以看出,MinIO 发布了.NET、Golang、Haskell、Java、JavaScript、Python 共 6 种语言的 SDK,接下来我们基于 Java SDK 来实现对 MinIO 的一些常规操作。


二 Java SDK

2.1 当前版本

截止目前(2023.12.22),Java SDK 的版本为 8.5.7,github 地址:minio/minio-java

与其他依赖相同,支持 maven、gradle 活 jar 包直接引入方式。我们以 Maven 为例:

<dependency>    <groupId>io.minio</groupId>    <artifactId>minio</artifactId>    <version>8.5.7</version></dependency>
复制代码

2.2 api 示例-文件上传

2.2.1 准备信息

这是一个官方示例。上传文件到 minio 服务器需要以下三个参数:

Endpoint : S3 服务的 Url

Access Key:minio 账号的 ak.

Secret Key:minio 的 sk.


ak、sk 创建/查询方法,可参考如下截图,在 Service Accounts 下,点击 Create service account 按钮创建账号。


在这个页面上,复制 Access Key 和 Secret Key 保存。


2.2.2 官方测试服务信息

注意,如果本地还没有搭建,可以先使用官方文档提供的两个测试服务地址:

MinIO:

MinioClient minioClient =    MinioClient.builder()        .endpoint("https://play.min.io")        .credentials("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG")        .build();
复制代码

AWS S3:

MinioClient minioClient =    MinioClient.builder()        .endpoint("https://s3.amazonaws.com")        .credentials("YOUR-ACCESSKEYID", "YOUR-SECRETACCESSKEY")        .build();
复制代码

2.2.3 文件上传代码示例

package com.freemark.demo.minio;
import io.minio.BucketExistsArgs;import io.minio.MakeBucketArgs;import io.minio.MinioClient;import io.minio.UploadObjectArgs;import io.minio.errors.MinioException;
import java.io.IOException;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;
public class FileUploader { /** * 这里配置自己的endpoint和ak sk */ public static String endPoint = "http://你的minio server ip:端口号"; public static String accessKey = "你的ak"; public static String secretKey = "你的sk"; public static void main(String[] args) throws IOException, NoSuchAlgorithmException, InvalidKeyException { try { // 创建minioClient,使用官方提供的示例地址和ak sk MinioClient minioClient = MinioClient.builder() .endpoint("https://play.min.io") .credentials("Q3AM3UQ867SPQQA43P2F", "zuf+tfteSlswRu7BJ86wekitnifILbZam1KYY3TG") .build();
// 如果指定的bucket不存在,则创建,否则使用已有bucket String bucketName = "asiatrip1"; boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build()); if (!found) { minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build()); } else { System.out.println("Bucket '" + bucketName + "' already exists."); }
String filePath = "/Users/lijingyong/Downloads/minio_test_text.txt"; String fileName = "minio_test_text.txt";
// 执行文件上传 minioClient.uploadObject( UploadObjectArgs.builder() .bucket(bucketName) .object(fileName) .filename(filePath) .build()); System.out.println("'" + filePath + "' 成功上传对象 '" + fileName + "' 到 bucket '" + bucketName + "'."); } catch (MinioException e) { System.out.println("Error occurred: " + e); System.out.println("HTTP trace: " + e.httpTrace()); } }}
复制代码

执行后打印如下信息:

如果使用的是自己搭建的 minio 服务地址及对应的 ak 和 sk,那么我们就能够看到在指定的 bucket 下有我们刚刚上传的文件。如下所示:

如果执行多次,会发现提示 bucket 已存在,不会重复创建,但文件会多次上传,覆盖上传。

2.3 完整 API 说明

其他完整的 API,我们也可以查看官方文档:https://min.io/docs/minio/linux/developers/java/API.html#bucketExists。下面以可能会经常用到的文件下载、删除完成本篇示例,其他可以查看文档,这里就不在赘述。

2.4 文件下载

2.4.1 文件下载

方法名:downloadObject

入参:DownloadObjectArgs,参数列表:

bucket: 要从哪个 bucket 下载文件

object: 要下载的对象名

filename:要保存的文件路径

使用如下代码,即可执行对指定 bucket 下指定对象的下载,下载的文件会保存在 filename 参数对应的路径下。

minioClient.downloadObject(  DownloadObjectArgs.builder()  .bucket("my-bucketname")  .object("my-objectname")  .filename("my-object-file")  .build());
复制代码

如果服务端文件进行了加密,那我们在下载时也需要增加 ssec 参数来做支持,

ServerSideEncryptionCustomerKey ssec =				new ServerSideEncryptionCustomerKey(						new SecretKeySpec(								"01234567890123456789012345678901".getBytes(StandardCharsets.UTF_8), "AES"));                minioClient.downloadObject(				DownloadObjectArgs.builder()						.bucket(bucketName)						.object(fileName)						.filename("/Users/xxx/Downloads/download_minio_test_text.txt")						.ssec(ssec)						.build());		System.out.println(fileName + "下载完毕"); 
复制代码

注意,如果我们使用的 minio 没有安装成带有 TLS 的服务,那么执行上述代码会报如下错误。

Minio 服务端加密是大部分文章都没有提到的,所以这里我们稍微展开说明一下。

2.5 Minio 服务端加密

参考Minio Cookbook 中文版 中的如何使用aws-cli调用Minio服务端加密,Minio 支持采用客户端提供的秘钥(SSE-C)进行 S3 服务端加密。客户端必须为 SSE-C 请求指定三个 HTTP 请求头:

1、算法标识符: X-Amz-Server-Side-Encryption-Customer-Algorithm 唯一的合法值是: AES256。

2、加密秘钥: X-Amz-Server-Side-Encryption-Customer-Key 加密秘钥必须是一个 256 位的 base64 编码的字符串。

3、加密密钥 MD5 校验和: X-Amz-Server-Side-Encryption-Customer-Key-MD5 加密密钥 MD5 校验和必须是秘钥的 MD5 和,注意是原始秘钥的 MD5 和,而不是 base64 编码之后的。

2.5.1 安全须知

  • 根据 S3 规范,minio 服务器将拒绝任何通过不安全(非 TLS)连接进行的 SSE-C 请求。 这意味着 SSE-C 必须是 TLS / HTTPS。

  • SSE-C 请求包含加密密钥。 如果通过非 TLS 连接进行 SSE-C 请求,则必须将 SSE-C 加密密钥视为受损。

  • 根据 S3 规范,SSE-C PUT 操作返回的 content-md5 与上传对象的 MD5-sum 不匹配。

  • Minio Server 使用防篡改加密方案来加密对象,并且不会保存加密密钥。 这意味着您有责任保管好加密密钥。 如果你丢失了某个对象的加密密钥,你将会丢失该对象。

  • Minio Server 期望 SSE-C 加密密钥是高熵的。加密密钥是不是密码。如果你想使用密码,请确保使用诸如 Argon2,scrypt 或 PBKDF2 的基于密码的密钥派生函数(PBKDF)来派生高熵密钥。

2.5.2 前提条件

minio 安装时需要安装成带有 TLS 的服务。从这里下载 Minio Server,安装方式参考文档Network Encryption (TLS) 生成证书。

这里需要注意的是,如果你使用的是自己签名的 TLS 证书,那么当你往 Minio Server 上传文件时,像 aws-cli 或者是 mc 这些工具就会报错。如果你想获得一个 CA 结构签名的 TLS 证书,请参考Let's Encrypt。自己签名的证书应该仅做为内部开发和测试。

2.5.3 使用 SSE-C 和 aws-cli

这里下载并安装 aws-cli。

假设你在本地运行了一个 Minio Server,地址是https://localhost:9000,并且使用的是自己签名的证书。为了绕过 TLS 证书的验证,你需要指定—no-verify-ssl。如果你的 Minio Server 使用的是一个 CA 认证的证书,那你永远永远永远不要指定`—no-verify-ssl,否则 aws-cli 会接受任何证书。

2.6 其他 SDK

2.6.1 对象删除

使用 removeObject 方法,支持删除单个对象、

// Remove object.minioClient.removeObject(    RemoveObjectArgs.builder().bucket("my-bucketname").object("my-objectname").build());
复制代码

删除指定的对象的某个版本:

// Remove versioned object.minioClient.removeObject(    RemoveObjectArgs.builder()        .bucket("my-bucketname")        .object("my-versioned-objectname")        .versionId("my-versionid")        .build());
复制代码

绕过治理模式删除版本控制的对象:

// Remove versioned object bypassing Governance mode.minioClient.removeObject(    RemoveObjectArgs.builder()        .bucket("my-bucketname")        .object("my-versioned-objectname")        .versionId("my-versionid")        .bypassRetentionMode(true)        .build());
复制代码

2.6.2 对象批量删除

使用 removeObjects,参数为对象 List:

List<DeleteObject> objects = new LinkedList<>();objects.add(new DeleteObject("my-objectname1"));objects.add(new DeleteObject("my-objectname2"));objects.add(new DeleteObject("my-objectname3"));Iterable<Result<DeleteError>> results =    minioClient.removeObjects(        RemoveObjectsArgs.builder().bucket("my-bucketname").objects(objects).build());for (Result<DeleteError> result : results) {  DeleteError error = result.get();  System.out.println(      "Error in deleting object " + error.objectName() + "; " + error.message());}
复制代码

2.6.3 其他 api

其他常用的 API 还包括获取 bucket 下的文件列表:listObjects,设置 bucket 生命周期:setBucketLifecycle 等等。因为官方 API 文档和其他文章提供的工具类中都有描述,这里就不再赘述了。工具类代码大家可以查看https://gitee.com/flamingskyline/template-engine并下载获取。


发布于: 刚刚阅读数: 5
用户头像

磨炼中成长,痛苦中前行 2017-10-22 加入

微信公众号【程序员架构进阶】。多年项目实践,架构设计经验。曲折中向前,分享经验和教训

评论

发布
暂无评论
MinIO对象存储——Java SDK_对象存储_程序员架构进阶_InfoQ写作社区