RustFS 是一款兼容 S3 协议的对象存储系统,支持通过 AWS S3 SDK 与系统进行集成。本文将以 AWS S3 Java SDK 为例,介绍如何从零开始搭建开发环境,连接 RustFS,并完成基本的对象存储操作。

一、集成 AWS S3 Java SDK

1.1 创建 Maven 项目

使用如下目录结构或在 IDE 中新建 Maven 项目:

rustfs-java-s3-demo/
├── pom.xml
└── src/
    └── main/
        └── java/
            └── com/
                └── example/
                    └── RustfsS3Example.java

1.2 添加依赖

pom.xml 中添加 AWS SDK 依赖:

<dependencies>
    <dependency>
        <groupId>software.amazon.awssdk</groupId>
        <artifactId>s3</artifactId>
        <version>2.25.27</version>
    </dependency>
</dependencies>

推荐使用 AWS SDK v2 版本,功能更完善,支持异步、响应式等模式。


二、连接并使用 RustFS

2.1 初始化 S3 客户端

package com.example;

import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.*;

import java.net.URI;
import java.nio.file.Paths;

public class RustfsS3Example {

    public static void main(String[] args) {
        // 1. 初始化 S3 客户端
        S3Client s3 = S3Client.builder()
                .endpointOverride(URI.create("http://192.168.1.100:9000")) // RustFS 地址
                .region(Region.US_EAST_1) // 可写死,RustFS 不校验 region
                .credentialsProvider(
                        StaticCredentialsProvider.create(
                                AwsBasicCredentials.create("rustfsadmin", "rustfssecret")
                        )
                )
                .forcePathStyle(true) // 关键配置!RustFS 需启用 Path-Style
                .build();

        // 2. 创建 Bucket
        String bucket = "my-bucket";
        try {
            s3.createBucket(CreateBucketRequest.builder().bucket(bucket).build());
            System.out.println("Bucket created: " + bucket);
        } catch (BucketAlreadyExistsException | BucketAlreadyOwnedByYouException e) {
            System.out.println("Bucket already exists.");
        }

        // 3. 上传文件
        s3.putObject(
                PutObjectRequest.builder().bucket(bucket).key("hello.txt").build(),
                Paths.get("hello.txt")
        );
        System.out.println("Uploaded hello.txt");

        // 4. 下载文件
        s3.getObject(
                GetObjectRequest.builder().bucket(bucket).key("hello.txt").build(),
                Paths.get("downloaded-hello.txt")
        );
        System.out.println("Downloaded hello.txt");

        // 5. 列出对象
        ListObjectsV2Response listResponse = s3.listObjectsV2(ListObjectsV2Request.builder().bucket(bucket).build());
        listResponse.contents().forEach(obj -> System.out.println("Found object: " + obj.key()));

        // 6. 删除对象
        s3.deleteObject(DeleteObjectRequest.builder().bucket(bucket).key("hello.txt").build());
        System.out.println("Deleted hello.txt");

        // 7. 删除桶(可选)
        // s3.deleteBucket(DeleteBucketRequest.builder().bucket(bucket).build());
    }
}

三、常见问题与排查

问题原因解决方法
S3Exception: 301 Moved Permanently未启用 path-style 或 region 错误设置 .forcePathStyle(true) 且 region 使用任意值
ConnectException: Connection refusedRustFS 未启动或端口不正确检查 RustFS 状态与端口
403 ForbiddenAccessKey / SecretKey 错误检查认证配置
上传失败无响应SDK 默认使用 HTTPS,RustFS 仅支持 HTTP(或需证书)使用 http:// 地址并配置 endpointOverride

四、附录

4.1 Maven 清单打包

打包项目:

mvn clean package

执行:

java -cp target/rustfs-java-s3-demo-1.0-SNAPSHOT.jar com.example.RustfsS3Example

4.2 RustFS 配置建议

  • 保证服务使用 HTTP 协议时关闭 SSL 校验。
  • 启用 CORS 支持(若用于 Web 前端)。
  • 推荐设置 max_object_sizemax_part_size 等限制,防止大文件传输失败。

好的,下面是 RustFS 使用 AWS S3 Java SDK 的高级功能示例补充,包括:

  • 预签名 URL(Presigned URL)生成与使用
  • 分片上传(Multipart Upload)完整流程

五、Java 高级功能示例

5.1 生成并使用 Presigned URL(预签名 URL)

Presigned URL 允许客户端在不暴露凭据的情况下,临时访问私有对象,广泛用于浏览器直接上传或下载文件场景。

5.1.1 添加依赖(v2 SDK 的 URL 签名位于 s3-presigner 模块)

<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>s3-presigner</artifactId>
    <version>2.25.27</version>
</dependency>

5.1.2 生成下载链接(GET)

import software.amazon.awssdk.services.s3.presigner.S3Presigner;
import software.amazon.awssdk.services.s3.presigner.model.GetObjectPresignRequest;

S3Presigner presigner = S3Presigner.builder()
        .endpointOverride(URI.create("http://192.168.1.100:9000"))
        .region(Region.US_EAST_1)
        .credentialsProvider(
            StaticCredentialsProvider.create(
                AwsBasicCredentials.create("rustfsadmin", "rustfssecret")
            )
        )
        .build();

GetObjectRequest getObjectRequest = GetObjectRequest.builder()
        .bucket("my-bucket")
        .key("hello.txt")
        .build();

GetObjectPresignRequest presignRequest = GetObjectPresignRequest.builder()
        .getObjectRequest(getObjectRequest)
        .signatureDuration(Duration.ofMinutes(15)) // 有效期15分钟
        .build();

PresignedGetObjectRequest presignedRequest = presigner.presignGetObject(presignRequest);

System.out.println("Presigned URL: " + presignedRequest.url());

🔗 使用浏览器打开链接,即可访问该对象。

5.1.3 上传 Presigned URL(PUT)

类似地,也可生成上传 URL:

PutObjectRequest putRequest = PutObjectRequest.builder()
        .bucket("my-bucket")
        .key("upload.txt")
        .build();

PresignedPutObjectRequest presignedPut = presigner.presignPutObject(
        PutObjectPresignRequest.builder()
                .putObjectRequest(putRequest)
                .signatureDuration(Duration.ofMinutes(10))
                .build()
);

System.out.println("Upload URL: " + presignedPut.url());

5.2 实现分片上传(Multipart Upload)

Multipart Upload 是大文件上传的推荐方式,可在网络波动时断点续传。

5.2.1 启动分片上传

CreateMultipartUploadRequest createRequest = CreateMultipartUploadRequest.builder()
        .bucket("my-bucket")
        .key("bigfile.zip")
        .build();

CreateMultipartUploadResponse createResponse = s3.createMultipartUpload(createRequest);
String uploadId = createResponse.uploadId();

5.2.2 上传各分片(Part)

List<CompletedPart> completedParts = new ArrayList<>();
for (int i = 1; i <= 3; i++) {
    String partPath = "part" + i + ".bin"; // 假设每个 part 为本地文件
    UploadPartRequest uploadPartRequest = UploadPartRequest.builder()
            .bucket("my-bucket")
            .key("bigfile.zip")
            .uploadId(uploadId)
            .partNumber(i)
            .build();

    UploadPartResponse uploadPartResponse = s3.uploadPart(uploadPartRequest, Paths.get(partPath));
    completedParts.add(
            CompletedPart.builder()
                    .partNumber(i)
                    .eTag(uploadPartResponse.eTag())
                    .build()
    );
}

5.2.3 完成分片上传

CompletedMultipartUpload completedUpload = CompletedMultipartUpload.builder()
        .parts(completedParts)
        .build();

CompleteMultipartUploadRequest completeRequest = CompleteMultipartUploadRequest.builder()
        .bucket("my-bucket")
        .key("bigfile.zip")
        .uploadId(uploadId)
        .multipartUpload(completedUpload)
        .build();

s3.completeMultipartUpload(completeRequest);
System.out.println("Multipart upload completed.");

5.2.4 异常中止上传(可选)

AbortMultipartUploadRequest abortRequest = AbortMultipartUploadRequest.builder()
        .bucket("my-bucket")
        .key("bigfile.zip")
        .uploadId(uploadId)
        .build();

s3.abortMultipartUpload(abortRequest);

商业支持购买咨询