使用 Java V2

IBM Cloud® Object Storage SDK for Java v2 提供了可充分利用 IBM Cloud Object Storage 的功能。

IBM Cloud Object Storage SDK for Java v2 功能全面,许多特性和功能超出了本指南的范围和篇幅。 有关详细的类和方法文档,请参阅 Java API 参考文档。 在 GitHub 存储库中可以找到源代码。

最新消息 v2

IBM Cloud Object Storage SDK for Java v2 是基于 AWS SDK v2 架构的现代化版本,带来了重大改进:

  • 不可变构建器:所有请求和响应对象都使用不可变构建器模式,以提高线程安全性
  • 现代软件包结构:新命名空间 com.ibm.cos.v2.*,组织更简洁
  • 增强的异步支持:为非阻塞操作引入 S3AsyncClient
  • 改进的流媒体:更好的流媒体应用程序接口,包括 RequestBodyResponseTransformer
  • 自动 IAM 令牌管理:SDK 自动处理 IAM 令牌刷新
  • 类型安全使用构建器加强编译时类型检查
  • 现代 HTTP 堆栈:支持 Apache HTTP 客户端和 Netty 异步操作

对于从 v1 迁移的开发人员,请参阅《 迁移指南 》。

获取 SDK

使用 IBM Cloud Object Storage Java SDK v2 的最简单方法是使用 Maven 管理依赖关系。 如果您不熟悉 Maven,可以使用《 Maven in 5-Minutes 指南》快速上手。

Maven 使用名为 pom.xml 的文件来指定 Java 项目所需的库(及其版本)。 以下是 pom.xml 文件示例,用于使用 IBM Cloud Object Storage Java SDK v2 连接 Object Storage。

<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.cos</groupId>
    <artifactId>docs</artifactId>
    <packaging>jar</packaging>
    <version>2.0-SNAPSHOT</version>
    <name>docs</name>
    <url>http://maven.apache.org</url>
    <dependencies>
        <dependency>
            <groupId>com.ibm.cos.v2</groupId>
            <artifactId>cos-java-sdk</artifactId>
            <version>1.0.1</version>
        </dependency>
    </dependencies>
</project>

SDK 参考资料

核心类

凭证

配置

流式方法

例外

创建客户机和获取凭证

在以下示例中,将通过提供凭证信息(API 密钥和服务实例标识)来创建和配置客户机 cos。 这些值还可以自动从凭证文件或环境变量中获取。

生成服务凭证后,生成的 JSON 文档可以保存到 ~/.bluemix/cos_credentials。 除非在客户机创建期间显式设置了其他凭证,否则 SDK 会自动从此文件中获取凭证。 如果 cos_credentials 文件包含 HMAC 密钥,那么客户机会使用签名进行认证;如果不包含 HMAC 密钥,客户机将使用提供的 API 密钥通过不记名令牌进行认证。

如果是从 AWS S3 进行迁移,那么还可以从 ~/.aws/credentials 中获取以下格式的凭证数据:

[default]
aws_access_key_id = {API_KEY}
aws_secret_access_key = {SERVICE_INSTANCE_ID}

如果 ~/.bluemix/cos_credentials~/.aws/credentials 同时存在,那么 cos_credentials 优先。

有关客户端构建的更多详情,请参阅 Java API 参考文档

代码示例

让我们从一个完整的示例类开始,了解一些基本功能。 该 CosExample 类可列出现有水桶中的对象,创建新水桶,然后列出服务实例中的所有水桶。

收集必需的信息

  • bucketNamenewBucketName唯一的 DNS 安全字符串。 因为存储区名称在整个系统中唯一,因此如果多次运行此示例,那么需要更改这些值。 删除后,名称会保留 10-15 分钟。
  • apiKey服务证书 中的值,如 apikey
  • serviceInstanceId服务证书 中的值,如 resource_instance_id
  • endpointUrl 是一个服务端点 URL,包括 https:// 协议。 这不是 服务证书 中的 endpoints 值。 有关端点的更多信息,请参阅 端点和存储位置
  • location 必须设置为 storageClass 的位置部分。 对于 us-south-standard,这将是 us-south。 此变量仅用于计算 HMAC 签名,但对于任何客户机,此变量都是必需的,包括使用 IAM API 密钥的此示例。
package com.cos;

import java.net.URI;
import java.util.List;

import com.ibm.cos.v2.auth.credentials.AwsCredentials;
import com.ibm.cos.v2.auth.credentials.StaticCredentialsProvider;
import com.ibm.cos.v2.auth.credentials.ibmOAuth.BasicIBMOAuthCredentials;
import com.ibm.cos.v2.regions.Region;
import com.ibm.cos.v2.services.s3.S3Client;
import com.ibm.cos.v2.services.s3.model.*;

public class CosExample {

    private static String COS_ENDPOINT = "<endpoint>";
    private static String COS_API_KEY_ID = "<api-key>";
    private static String COS_SERVICE_INSTANCE_ID = "<service-instance-id>";
    private static String COS_LOCATION = "<location>";

    public static void main(String[] args) {
        System.out.println("Current time: " + new java.util.Date());

        // Create IBM COS credentials using API key
        AwsCredentials credentials = new BasicIBMOAuthCredentials(COS_API_KEY_ID, COS_SERVICE_INSTANCE_ID);

        // Create the S3 client
        S3Client cosClient = S3Client.builder()
                .endpointOverride(URI.create(COS_ENDPOINT))
                .credentialsProvider(StaticCredentialsProvider.create(credentials))
                .region(Region.of(COS_LOCATION))
                .build();

        listObjects("my-bucket", cosClient);
        createBucket("my-new-bucket", cosClient);
        listBuckets(cosClient);

        cosClient.close();
    }

    public static void listObjects(String bucketName, S3Client cosClient) {
        System.out.println("Listing objects in bucket: " + bucketName);

        ListObjectsV2Request request = ListObjectsV2Request.builder()
                .bucket(bucketName)
                .build();

        ListObjectsV2Response response = cosClient.listObjectsV2(request);
        List<S3Object> objects = response.contents();

        for (S3Object object : objects) {
            System.out.println("Item: " + object.key() + " (" + object.size() + " bytes)");
        }
    }

    public static void createBucket(String bucketName, S3Client cosClient) {
        System.out.println("Creating bucket: " + bucketName);

        CreateBucketRequest request = CreateBucketRequest.builder()
                .bucket(bucketName)
                .build();

        cosClient.createBucket(request);
        System.out.println("Bucket created: " + bucketName);
    }

    public static void listBuckets(S3Client cosClient) {
        System.out.println("Listing buckets:");

        ListBucketsResponse response = cosClient.listBuckets();
        List<Bucket> buckets = response.buckets();

        for (Bucket bucket : buckets) {
            System.out.println("Bucket Name: " + bucket.name());
        }
    }
}

主要参考资料

确定端点

有关端点的更多信息,请参阅端点和存储位置

端点也遵循这一模式:https://s3.{region}.cloud-object-storage.appdomain.cloud

示例:

  • 美国南部: https://s3.us-south.cloud-object-storage.appdomain.cloud
  • 美国东部: https://s3.us-east.cloud-object-storage.appdomain.cloud
  • 欧盟 英国 https://s3.eu-gb.cloud-object-storage.appdomain.cloud

创建新存储区

public static void createBucket(String bucketName, S3Client cosClient) {
    System.out.println("Creating new bucket: " + bucketName);

    CreateBucketRequest request = CreateBucketRequest.builder()
            .bucket(bucketName)
            .build();

    cosClient.createBucket(request);

    System.out.println("Bucket: " + bucketName + " created!");
}

密钥引用

创建使用其他存储类的存储区

public static void createBucketWithStorageClass(String bucketName, String storageClass, String location, S3Client cosClient) {
    System.out.println("Creating bucket: " + bucketName + " with storage class: " + storageClass);

    CreateBucketRequest request = CreateBucketRequest.builder()
            .bucket(bucketName)
            .ibmServiceInstanceId(COS_SERVICE_INSTANCE_ID)
            .build();

    cosClient.createBucket(request);

    System.out.println("Bucket: " + bucketName + " created with " + storageClass + " class storage!");
}

存储类选项包括

  • us-south-standard / us-east-standard / eu-gb-standard- 标准存储
  • us-south-vault / us-east-vault / eu-gb-vault- 金库存储
  • us-south-cold / us-east-cold / eu-gb-cold- 冷库储存
  • us-south-flex / us-east-flex / eu-gb-flex- 灵活存储

密钥引用

创建新的文本文件

public static void createTextFile(String bucketName, String itemName, String fileText, S3Client cosClient) {
    System.out.println("Creating new item: " + itemName);

    PutObjectRequest request = PutObjectRequest.builder()
            .bucket(bucketName)
            .key(itemName)
            .build();

    cosClient.putObject(request, RequestBody.fromString(fileText));

    System.out.println("Item: " + itemName + " created!");
}

主要参考资料

通过文件上传对象

public static void putObject(String bucketName, String itemName, String filePath, S3Client cosClient) {
    System.out.println("Creating new item: " + itemName);

    PutObjectRequest request = PutObjectRequest.builder()
            .bucket(bucketName)
            .key(itemName)
            .build();

    cosClient.putObject(request, RequestBody.fromFile(new File(filePath)));

    System.out.println("Item: " + itemName + " created!");
}

主要参考资料

使用流上传对象

public static void putObjectStream(String bucketName, String itemName, InputStream inputStream, long contentLength, S3Client cosClient) {
    System.out.println("Creating new item: " + itemName + " from input stream");

    PutObjectRequest request = PutObjectRequest.builder()
            .bucket(bucketName)
            .key(itemName)
            .contentLength(contentLength)
            .build();

    cosClient.putObject(request, RequestBody.fromInputStream(inputStream, contentLength));

    System.out.println("Item: " + itemName + " created!");
}

主要参考资料

将对象下载到文件

public static void getObject(String bucketName, String itemName, String filePath, S3Client cosClient) {
    System.out.println("Retrieving item: " + itemName);

    GetObjectRequest request = GetObjectRequest.builder()
            .bucket(bucketName)
            .key(itemName)
            .build();

    cosClient.getObject(request, ResponseTransformer.toFile(new File(filePath)));

    System.out.println("Item: " + itemName + " downloaded to: " + filePath);
}

主要参考资料

使用流下载对象

public static void getObjectStream(String bucketName, String itemName, S3Client cosClient) {
    System.out.println("Retrieving item: " + itemName + " as stream");

    GetObjectRequest request = GetObjectRequest.builder()
            .bucket(bucketName)
            .key(itemName)
            .build();

    ResponseInputStream<GetObjectResponse> response = cosClient.getObject(request);

    try (InputStream inputStream = response) {
        // Process the input stream
        byte[] buffer = new byte[1024];
        int bytesRead;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            // Process bytes
            System.out.write(buffer, 0, bytesRead);
        }
    } catch (IOException e) {
        System.err.println("Error reading object: " + e.getMessage());
    }

    System.out.println("\nItem: " + itemName + " retrieved!");
}

主要参考资料

复制对象

public static void copyObject(String sourceBucketName, String sourceKey, String destinationBucketName, String destinationKey, S3Client cosClient) {
    System.out.println("Copying item: " + sourceKey + " from bucket: " + sourceBucketName +
                       " to: " + destinationKey + " in bucket: " + destinationBucketName);

    CopyObjectRequest request = CopyObjectRequest.builder()
            .sourceBucket(sourceBucketName)
            .sourceKey(sourceKey)
            .destinationBucket(destinationBucketName)
            .destinationKey(destinationKey)
            .build();

    cosClient.copyObject(request);

    System.out.println("Item: " + sourceKey + " copied!");
}

主要参考资料

列出可用存储区

public static void listBuckets(S3Client cosClient) {
    System.out.println("Listing buckets:");

    ListBucketsResponse response = cosClient.listBuckets();
    List<Bucket> buckets = response.buckets();

    for (Bucket bucket : buckets) {
        System.out.println("Bucket Name: " + bucket.name());
    }
}

主要参考资料

获取特定项的文件内容

public static void getItem(String bucketName, String itemName, S3Client cosClient) {
    System.out.println("Retrieving item: " + itemName);

    GetObjectRequest request = GetObjectRequest.builder()
            .bucket(bucketName)
            .key(itemName)
            .build();

    ResponseInputStream<GetObjectResponse> response = cosClient.getObject(request);

    try {
        String content = new String(response.readAllBytes(), StandardCharsets.UTF_8);
        System.out.println("File Contents:\n" + content);
    } catch (IOException e) {
        System.err.println("Error reading object: " + e.getMessage());
    }
}

主要参考资料

从存储区中删除一个项

public static void deleteItem(String bucketName, String itemName, S3Client cosClient) {
    System.out.println("Deleting item: " + itemName);

    DeleteObjectRequest request = DeleteObjectRequest.builder()
            .bucket(bucketName)
            .key(itemName)
            .build();

    cosClient.deleteObject(request);

    System.out.println("Item: " + itemName + " deleted!");
}

主要参考资料

从存储区中删除多个项

public static void deleteMultipleItems(String bucketName, List<String> itemNames, S3Client cosClient) {
    System.out.println("Deleting multiple items from bucket: " + bucketName);

    List<ObjectIdentifier> objectsToDelete = itemNames.stream()
            .map(key -> ObjectIdentifier.builder().key(key).build())
            .collect(Collectors.toList());

    Delete delete = Delete.builder()
            .objects(objectsToDelete)
            .build();

    DeleteObjectsRequest request = DeleteObjectsRequest.builder()
            .bucket(bucketName)
            .delete(delete)
            .build();

    DeleteObjectsResponse response = cosClient.deleteObjects(request);

    System.out.println("Deleted " + response.deleted().size() + " items!");
}

主要参考资料

删除存储区

水桶必须清空后才能删除。

public static void deleteBucket(String bucketName, S3Client cosClient) {
    System.out.println("Deleting bucket: " + bucketName);

    DeleteBucketRequest request = DeleteBucketRequest.builder()
            .bucket(bucketName)
            .build();

    cosClient.deleteBucket(request);

    System.out.println("Bucket: " + bucketName + " deleted!");
}

主要参考资料

检查对象是否公共可读

public static boolean isObjectPubliclyReadable(String bucketName, String objectKey, S3Client cosClient) {
    System.out.println("Checking if object is publicly readable: " + objectKey);

    try {
        GetObjectAclRequest request = GetObjectAclRequest.builder()
                .bucket(bucketName)
                .key(objectKey)
                .build();

        GetObjectAclResponse response = cosClient.getObjectAcl(request);

        for (Grant grant : response.grants()) {
            if (grant.grantee().type() == Type.GROUP &&
                grant.grantee().uri() != null &&
                grant.grantee().uri().contains("AllUsers") &&
                grant.permission() == Permission.READ) {
                System.out.println("Object is publicly readable");
                return true;
            }
        }

        System.out.println("Object is not publicly readable");
        return false;
    } catch (S3Exception e) {
        System.err.println("Error checking object ACL: " + e.getMessage());
        return false;
    }
}

主要参考资料

执行分块上传

使用较大的对象时,建议使用分块上传操作将对象写入 IBM Cloud Object Storage。 可以将单个对象的上传作为一组分块来执行,这些分块可以按任意顺序单独上传,也可以并行上传。 上传完成后,IBM Cloud Object Storage 会将所有分块显示为单个对象。

分块上传仅可用于大于 5 MB 的对象。 对于小于 50 GB 的对象,建议的分块大小为 20 MB 到 100 MB,以实现最佳性能。 对于更大的对象,可以增大分块大小,而不会对性能产生重大影响。

public static void multipartUpload(String bucketName, String itemName, String filePath, S3Client cosClient) {
    System.out.println("Starting multipart upload for: " + itemName);

    // Step 1: Initiate multipart upload
    CreateMultipartUploadRequest initiateRequest = CreateMultipartUploadRequest.builder()
            .bucket(bucketName)
            .key(itemName)
            .build();

    CreateMultipartUploadResponse initiateResponse = cosClient.createMultipartUpload(initiateRequest);
    String uploadId = initiateResponse.uploadId();
    System.out.println("Upload ID: " + uploadId);

    // Step 2: Upload parts
    int partNumber = 1;
    List<CompletedPart> completedParts = new ArrayList<>();
    ByteBuffer buffer = ByteBuffer.allocate(5 * 1024 * 1024); // 5 MB parts

    try (RandomAccessFile file = new RandomAccessFile(filePath, "r")) {
        long fileSize = file.length();
        long position = 0;

        while (position < fileSize) {
            file.seek(position);
            long bytesRead = file.getChannel().read(buffer);

            buffer.flip();

            UploadPartRequest uploadPartRequest = UploadPartRequest.builder()
                    .bucket(bucketName)
                    .key(itemName)
                    .uploadId(uploadId)
                    .partNumber(partNumber)
                    .build();

            UploadPartResponse partResponse = cosClient.uploadPart(
                    uploadPartRequest,
                    RequestBody.fromByteBuffer(buffer)
            );

            CompletedPart part = CompletedPart.builder()
                    .partNumber(partNumber)
                    .eTag(partResponse.eTag())
                    .build();
            completedParts.add(part);

            System.out.println("Uploaded part " + partNumber);

            buffer.clear();
            position += bytesRead;
            partNumber++;
        }
    } catch (IOException e) {
        System.err.println("Error during multipart upload: " + e.getMessage());

        // Abort the multipart upload on error
        AbortMultipartUploadRequest abortRequest = AbortMultipartUploadRequest.builder()
                .bucket(bucketName)
                .key(itemName)
                .uploadId(uploadId)
                .build();
        cosClient.abortMultipartUpload(abortRequest);
        return;
    }

    // Step 3: Complete multipart upload
    CompletedMultipartUpload completedUpload = CompletedMultipartUpload.builder()
            .parts(completedParts)
            .build();

    CompleteMultipartUploadRequest completeRequest = CompleteMultipartUploadRequest.builder()
            .bucket(bucketName)
            .key(itemName)
            .uploadId(uploadId)
            .multipartUpload(completedUpload)
            .build();

    cosClient.completeMultipartUpload(completeRequest);

    System.out.println("Multipart upload completed for: " + itemName);
}

主要参考资料

使用不可变对象存储器

用户可以配置具有不可变 Object Storage 策略的存储桶,以防止对象在规定时间内被修改或删除。 保留期可以按对象指定,也可以继承在数据桶上设置的默认保留期。

为水桶添加保护配置

PUT 操作实现使用 protection 查询参数来设置现有存储区的保留时间参数。 此操作允许您设置或更改最短保留期、缺省保留期和最长保留期。 此操作还允许您更改存储区的保护状态。

对于写入受保护存储区的对象,在保护时间段到期并且除去了对象上的所有合法保留之前,无法删除这些对象。 除非在创建对象时提供了特定于对象的值,否则将向对象提供存储区的缺省保留时间值。 受保护存储桶中不再保留的对象(保留期已过,且对象没有任何合法保留),在被覆盖后将再次被保留。 可以在对象覆盖请求中提供新的保留期,否则会为对象提供存储区的缺省保留时间。

保留期设置 MinimumRetentionDefaultRetentionMaximumRetention 的最小和最大支持值分别为 0 天和 365243 天(1000 年)。

public static void addProtectionConfigurationToBucket(String bucketName, S3Client cosClient) {
    System.out.println("Adding protection configuration to bucket: " + bucketName);

    BucketProtectionConfiguration protectionConfig = BucketProtectionConfiguration.builder()
            .status(BucketProtectionStatus.RETENTION)
            .minimumRetention(BucketProtectionMinimumRetention.builder()
                    .days(10)
                    .build())
            .defaultRetention(BucketProtectionDefaultRetention.builder()
                    .days(100)
                    .build())
            .maximumRetention(BucketProtectionMaximumRetention.builder()
                    .days(1000)
                    .build())
            .build();

    PutBucketProtectionConfigurationRequest request = PutBucketProtectionConfigurationRequest.builder()
            .bucket(bucketName)
            .protectionConfiguration(protectionConfig)
            .build();

    cosClient.putBucketProtectionConfiguration(request);

    System.out.println("Protection configuration added!");
}

获取水桶的保护配置

public static void getProtectionConfigurationOnBucket(String bucketName, S3Client cosClient) {
    System.out.println("Retrieving protection configuration for bucket: " + bucketName);

    GetBucketProtectionConfigurationRequest request = GetBucketProtectionConfigurationRequest.builder()
            .bucket(bucketName)
            .build();

    GetBucketProtectionConfigurationResponse response = cosClient.getBucketProtectionConfiguration(request);

    System.out.println("Status: " + response.status());
    System.out.println("Minimum Retention (days): " + response.minimumRetention().days());
    System.out.println("Default Retention (days): " + response.defaultRetention().days());
    System.out.println("Maximum Retention (days): " + response.maximumRetention().days());
}

上传带保留功能的受保护对象

受保护存储桶中不再保留的对象(保留期已过,且对象没有任何合法保留),在被覆盖后将再次被保留。 可以在对象覆盖请求中提供新的保留期,否则会为对象提供存储区的缺省保留时间。

在将对象上传到受保护的存储桶时,可以使用自定义标头指定保留参数:

类型 描述
Retention-Period 非负整数(秒) 要在对象上存储的保留期(以秒为单位)。 在保留期中指定的时间长度到期之前,无法覆盖也无法删除对象。 如果指定了该字段和 Retention-Expiration-Date,则会返回 400 错误。 如果这两项均未指定,将使用存储区的 DefaultRetention 时间段。 0 (0) 是一个合法值,前提是数据桶的最短保留时间也是 0。
Retention-Expiration-Date 日期(ISO 8601 格式) 合法删除或修改对象的日期。 只能指定此项或 Retention-Period 标头。 如果同时指定这两个参数,将返回 400 错误。 如果这两项均未指定,将使用存储区的 DefaultRetention 时间段。
Retention-Legal-Hold-Id string 要应用于对象的单个合法保留。 合法保留是一个 Y 字符长字符串。 在除去与对象关联的所有合法保留之前,无法覆盖或删除对象。
public static void uploadProtectedObject(String bucketName, String objectKey, String filePath, S3Client cosClient) {
    System.out.println("Uploading protected object with retention: " + objectKey);

    // Option 1: Upload with retention period (in seconds)
    PutObjectRequest requestWithPeriod = PutObjectRequest.builder()
            .bucket(bucketName)
            .key(objectKey)
            .retentionPeriod(2592000L)  // 30 days in seconds
            .build();

    cosClient.putObject(requestWithPeriod, RequestBody.fromFile(new File(filePath)));
    System.out.println("Object uploaded with 30-day retention period");
}

public static void uploadProtectedObjectWithExpirationDate(String bucketName, String objectKey, String filePath, S3Client cosClient) {
    System.out.println("Uploading protected object with expiration date: " + objectKey);

    // Option 2: Upload with retention expiration date
    Instant expirationDate = Instant.now().plus(90, ChronoUnit.DAYS);

    PutObjectRequest requestWithDate = PutObjectRequest.builder()
            .bucket(bucketName)
            .key(objectKey)
            .retentionExpirationDate(expirationDate)
            .build();

    cosClient.putObject(requestWithDate, RequestBody.fromFile(new File(filePath)));
    System.out.println("Object uploaded with expiration date: " + expirationDate);
}

public static void uploadProtectedObjectWithLegalHold(String bucketName, String objectKey, String filePath, String legalHoldId, S3Client cosClient) {
    System.out.println("Uploading protected object with legal hold: " + objectKey);

    // Option 3: Upload with legal hold
    PutObjectRequest requestWithLegalHold = PutObjectRequest.builder()
            .bucket(bucketName)
            .key(objectKey)
            .retentionLegalHoldId(legalHoldId)
            .build();

    cosClient.putObject(requestWithLegalHold, RequestBody.fromFile(new File(filePath)));
    System.out.println("Object uploaded with legal hold: " + legalHoldId);
}

public static void uploadProtectedObjectWithMultipleRetentionOptions(String bucketName, String objectKey, String filePath, String legalHoldId, S3Client cosClient) {
    System.out.println("Uploading protected object with retention period and legal hold: " + objectKey);

    // Option 4: Combine retention period with legal hold
    PutObjectRequest request = PutObjectRequest.builder()
            .bucket(bucketName)
            .key(objectKey)
            .retentionPeriod(2592000L)  // 30 days
            .retentionLegalHoldId(legalHoldId)
            .build();

    cosClient.putObject(request, RequestBody.fromFile(new File(filePath)));
    System.out.println("Object uploaded with retention and legal hold");
}

重要说明:

  • 不能在同一请求中同时指定 Retention-PeriodRetention-Expiration-Date
  • 如果两个保留参数都未指定,则会应用数据桶的默认保留期。
  • 法律保留可与保留期相结合。
  • 在保留期满和所有法律保留取消之前,不能删除或覆盖保留中或法律保留中的对象。

主要参考资料

延长受保护对象的保留期限

对象的保留期只能延长。 不能在当前配置值的基础上缩短。

保留时间延长值可通过以下三种方式之一进行设置:

  • 当前值的额外时间additionalRetentionPeriod 或类似方法)
  • 新的延长时间(秒 (extendRetentionFromCurrentTime 或类似方法)
  • 对象的新保留到期日newRetentionExpirationDate 或类似方法)

根据 extendRetention 请求中设置的参数,对象元数据中存储的当前保留期可通过给定额外时间延长,也可替换为新值。 在任何情况下,都会对照当前保留期检查扩展保留参数,只有当更新的保留期大于当前保留期时,才会接受扩展参数。

受保护存储桶中不再保留的对象(保留期已过,且对象没有任何合法保留),在被覆盖后将再次被保留。 可以在对象覆盖请求中提供新的保留期,否则会为对象提供存储区的缺省保留时间。

public static void extendRetentionPeriodOnObject(String bucketName, String objectName, Long additionalSeconds, S3Client cosClient) {
    System.out.printf("Extending the retention period on %s in bucket %s by %s seconds.%n", objectName, bucketName, additionalSeconds);

    ExtendObjectRetentionRequest request = ExtendObjectRetentionRequest.builder()
            .bucket(bucketName)
            .key(objectName)
            .additionalRetentionPeriod(additionalSeconds)
            .build();

    cosClient.extendObjectRetention(request);

    System.out.printf("Retention period extended on %s by %s seconds%n", objectName, additionalSeconds);
}

主要参考资料

使用 Key Protect

可以将 Key Protect 添加到存储区,以对云中的敏感数据进行静态加密。

用 Key Protect

public static void createBucketWithKeyProtect(String bucketName, String kpRootKeyCrn, S3Client cosClient) {
    System.out.println("Creating bucket with Key Protect: " + bucketName);

    CreateBucketRequest request = CreateBucketRequest.builder()
            .bucket(bucketName)
            .ibmSSEKPEncryptionAlgorithm("AES256")
            .ibmSSEKPCustomerRootKeyCrn(kpRootKeyCrn)
            .build();

    cosClient.createBucket(request);

    System.out.println("Bucket created with Key Protect encryption!");
}

将对象上传到启用了 Key Protect 的邮筒

public static void putObjectToKPBucket(String bucketName, String objectKey, String filePath, S3Client cosClient) {
    System.out.println("Uploading object to Key Protect enabled bucket");

    PutObjectRequest request = PutObjectRequest.builder()
            .bucket(bucketName)
            .key(objectKey)
            .build();

    cosClient.putObject(request, RequestBody.fromFile(new File(filePath)));

    System.out.println("Object uploaded with Key Protect encryption!");
}

使用传输管理器上传更大的对象

传输管理器提供了一个简单的应用程序接口,用于向 IBM Cloud Object Storage 上传和下载对象。

import com.ibm.cos.v2.transfer.s3.S3TransferManager;
import com.ibm.cos.v2.transfer.s3.model.*;

public static void uploadWithTransferManager(String bucketName, String objectKey, String filePath, S3Client cosClient) {
    System.out.println("Uploading with Transfer Manager: " + objectKey);

    // Create Transfer Manager
    S3TransferManager transferManager = S3TransferManager.builder()
            .s3Client(cosClient)
            .build();

    try {
        // Upload file
        UploadFileRequest uploadRequest = UploadFileRequest.builder()
                .putObjectRequest(req -> req.bucket(bucketName).key(objectKey))
                .source(Paths.get(filePath))
                .build();

        FileUpload upload = transferManager.uploadFile(uploadRequest);

        // Wait for upload to complete
        CompletedFileUpload completedUpload = upload.completionFuture().join();

        System.out.println("Upload completed: " + completedUpload.response().eTag());
    } finally {
        transferManager.close();
    }
}

主要参考资料

更新元数据

更新现有对象的元数据

public static void updateObjectMetadata(String bucketName, String objectKey, S3Client cosClient) {
    System.out.println("Updating metadata for object: " + objectKey);

    // Create new metadata
    Map<String, String> newMetadata = new HashMap<>();
    newMetadata.put("updated-by", "admin");
    newMetadata.put("update-date", LocalDate.now().toString());

    // Copy object to itself with new metadata
    CopyObjectRequest request = CopyObjectRequest.builder()
            .sourceBucket(bucketName)
            .sourceKey(objectKey)
            .destinationBucket(bucketName)
            .destinationKey(objectKey)
            .metadata(newMetadata)
            .metadataDirective(MetadataDirective.REPLACE)
            .build();

    cosClient.copyObject(request);

    System.out.println("Metadata updated!");
}

主要参考资料

使用 Aspera 高速传输

Aspera 高速传输集成可通过 IBM Aspera SDK 实现。 有关与 IBM Cloud Object Storage 集成的详细信息,请参阅 Aspera 文档

对于 Java 应用程序,您可以将 Aspera Transfer SDK 与 IBM Cloud Object Storage SDK v2 并用,以实现大文件的高速传输。

使用对象锁定

对象锁允许你使用“一次写入-多次读取”(WORM)模式来存储对象。 对象锁可在一定时间内或无限期防止对象被删除或覆盖。

创建启用对象锁的水桶

对象锁定必须在创建数据桶时启用,并且不能添加到现有的数据桶中。

public static void createBucketWithObjectLock(String bucketName, S3Client cosClient) {
    System.out.println("Creating bucket with Object Lock: " + bucketName);

    CreateBucketRequest request = CreateBucketRequest.builder()
            .bucket(bucketName)
            .objectLockEnabledForBucket(true)
            .build();

    cosClient.createBucket(request);

    System.out.println("Bucket created with Object Lock enabled!");
}

设置对象锁定保留

您可以设置对象的保留时间,以防止其被删除或覆盖。 有两种保留模式可供选择:

  • 符合性:任何用户(包括 root 用户)都不能覆盖或删除对象。
  • 管理:拥有特殊权限的用户可以更改保留设置或删除对象。
public static void putObjectRetention(String bucketName, String objectKey, S3Client cosClient) {
    System.out.println("Setting object retention for: " + objectKey);

    // Create retention period of 90 days
    Instant retainUntil = Instant.now().plus(90, ChronoUnit.DAYS);

    // Create object lock retention with COMPLIANCE mode
    ObjectLockRetention retention = ObjectLockRetention.builder()
            .mode(ObjectLockRetentionMode.COMPLIANCE)
            .retainUntilDate(retainUntil)
            .build();

    // Apply retention to object
    PutObjectRetentionRequest request = PutObjectRetentionRequest.builder()
            .bucket(bucketName)
            .key(objectKey)
            .retention(retention)
            .build();

    cosClient.putObjectRetention(request);

    System.out.println("Object retention set until: " + retainUntil);
}

获取对象锁保留信息

public static void getObjectRetention(String bucketName, String objectKey, S3Client cosClient) {
    System.out.println("Getting object retention for: " + objectKey);

    GetObjectRetentionRequest request = GetObjectRetentionRequest.builder()
            .bucket(bucketName)
            .key(objectKey)
            .build();

    GetObjectRetentionResponse response = cosClient.getObjectRetention(request);

    System.out.println("Retention Mode: " + response.retention().mode());
    System.out.println("Retain Until: " + response.retention().retainUntilDate());
}

设置对象锁定合法保持

法律保留提供的保护与保留期相同,但没有终止日期。 法律保留在明确取消之前一直有效。

public static void putObjectLegalHold(String bucketName, String objectKey, S3Client cosClient) {
    System.out.println("Setting legal hold on: " + objectKey);

    ObjectLockLegalHold legalHold = ObjectLockLegalHold.builder()
            .status(ObjectLockLegalHoldStatus.ON)
            .build();

    PutObjectLegalHoldRequest request = PutObjectLegalHoldRequest.builder()
            .bucket(bucketName)
            .key(objectKey)
            .legalHold(legalHold)
            .build();

    cosClient.putObjectLegalHold(request);

    System.out.println("Legal hold applied!");
}

获取对象锁的合法保留状态

public static void getObjectLegalHold(String bucketName, String objectKey, S3Client cosClient) {
    System.out.println("Getting legal hold status for: " + objectKey);

    GetObjectLegalHoldRequest request = GetObjectLegalHoldRequest.builder()
            .bucket(bucketName)
            .key(objectKey)
            .build();

    GetObjectLegalHoldResponse response = cosClient.getObjectLegalHold(request);

    System.out.println("Legal Hold Status: " + response.legalHold().status());
}

主要参考资料

使用水桶生命周期配置

生命周期配置可让您定义 IBM Cloud Object Storage 适用于一组对象的操作。 您可以使用生命周期策略将对象过渡到不同的存储类别,或在指定时间段后使对象过期。

在水桶上设置生命周期配置

public static void putBucketLifecycle(String bucketName, S3Client cosClient) {
    System.out.println("Setting lifecycle configuration on bucket: " + bucketName);

    // Create a transition to move objects to GLACIER after 30 days
    Transition transition = Transition.builder()
            .days(30)
            .storageClass(StorageClass.GLACIER)
            .build();

    // Create lifecycle rule filter
    LifecycleRuleFilter ruleFilter = LifecycleRuleFilter.builder()
            .prefix("archive/")  // Apply to objects with this prefix
            .build();

    // Create lifecycle rule
    LifecycleRule rule = LifecycleRule.builder()
            .id("archive-old-objects")
            .filter(ruleFilter)
            .transitions(transition)
            .status(ExpirationStatus.ENABLED)
            .build();

    // Create lifecycle configuration
    BucketLifecycleConfiguration lifecycleConfig = BucketLifecycleConfiguration.builder()
            .rules(rule)
            .build();

    // Apply lifecycle configuration to bucket
    PutBucketLifecycleConfigurationRequest request = PutBucketLifecycleConfigurationRequest.builder()
            .bucket(bucketName)
            .lifecycleConfiguration(lifecycleConfig)
            .build();

    cosClient.putBucketLifecycleConfiguration(request);

    System.out.println("Lifecycle configuration applied!");
}

获取水桶的生命周期配置

public static void getBucketLifecycle(String bucketName, S3Client cosClient) {
    System.out.println("Getting lifecycle configuration for bucket: " + bucketName);

    GetBucketLifecycleConfigurationRequest request = GetBucketLifecycleConfigurationRequest.builder()
            .bucket(bucketName)
            .build();

    GetBucketLifecycleConfigurationResponse response = cosClient.getBucketLifecycleConfiguration(request);

    System.out.println("Found " + response.rules().size() + " lifecycle rules:");

    for (LifecycleRule rule : response.rules()) {
        System.out.println("  Rule ID: " + rule.id());
        System.out.println("  Status: " + rule.status());
        if (rule.hasTransitions()) {
            for (Transition t : rule.transitions()) {
                System.out.println("  Transition after " + t.days() + " days to " + t.storageClass());
            }
        }
    }
}

删除水桶的生命周期配置

public static void deleteBucketLifecycle(String bucketName, S3Client cosClient) {
    System.out.println("Deleting lifecycle configuration from bucket: " + bucketName);

    DeleteBucketLifecycleRequest request = DeleteBucketLifecycleRequest.builder()
            .bucket(bucketName)
            .build();

    cosClient.deleteBucketLifecycle(request);

    System.out.println("Lifecycle configuration deleted!");
}

主要参考资料

使用水桶版本控制

版本管理可让你在同一个数据桶中保存一个对象的多个版本。 这可以帮助您从意外的用户操作和应用程序故障中恢复。

在水桶上启用版本控制

public static void enableBucketVersioning(String bucketName, S3Client cosClient) {
    System.out.println("Enabling versioning on bucket: " + bucketName);

    VersioningConfiguration versioningConfig = VersioningConfiguration.builder()
            .status(BucketVersioningStatus.ENABLED)
            .build();

    PutBucketVersioningRequest request = PutBucketVersioningRequest.builder()
            .bucket(bucketName)
            .versioningConfiguration(versioningConfig)
            .build();

    cosClient.putBucketVersioning(request);

    System.out.println("Versioning enabled!");
}

获取水桶版本状态

public static void getBucketVersioning(String bucketName, S3Client cosClient) {
    System.out.println("Getting versioning status for bucket: " + bucketName);

    GetBucketVersioningRequest request = GetBucketVersioningRequest.builder()
            .bucket(bucketName)
            .build();

    GetBucketVersioningResponse response = cosClient.getBucketVersioning(request);

    System.out.println("Versioning Status: " + response.status());
}

列出对象版本

public static void listObjectVersions(String bucketName, S3Client cosClient) {
    System.out.println("Listing object versions in bucket: " + bucketName);

    ListObjectVersionsRequest request = ListObjectVersionsRequest.builder()
            .bucket(bucketName)
            .build();

    ListObjectVersionsResponse response = cosClient.listObjectVersions(request);

    System.out.println("Versions:");
    for (ObjectVersion version : response.versions()) {
        System.out.println("  Key: " + version.key());
        System.out.println("  Version ID: " + version.versionId());
        System.out.println("  Is Latest: " + version.isLatest());
        System.out.println("  Last Modified: " + version.lastModified());
        System.out.println();
    }
}

删除特定对象版本

public static void deleteObjectVersion(String bucketName, String objectKey, String versionId, S3Client cosClient) {
    System.out.println("Deleting version " + versionId + " of object: " + objectKey);

    DeleteObjectRequest request = DeleteObjectRequest.builder()
            .bucket(bucketName)
            .key(objectKey)
            .versionId(versionId)
            .build();

    cosClient.deleteObject(request);

    System.out.println("Object version deleted!");
}

主要参考资料


使用扩展水桶列表

IBM Cloud Object Storage 提供了一个扩展的列表 API,可返回有关存储桶的其他元数据,包括位置和存储类别信息。

public static void listBucketsExtended(S3Client cosClient) {
    System.out.println("Listing buckets with extended information:");

    ListBucketsExtendedRequest request = ListBucketsExtendedRequest.builder().build();

    ListBucketsExtendedResponse response = cosClient.listBucketsExtended(request);

    for (Bucket bucket : response.buckets()) {
        System.out.println("Bucket Name: " + bucket.name());
        System.out.println("  Creation Date: " + bucket.creationDate());

        // Extended metadata (IBM-specific)
        if (bucket.locationConstraint() != null) {
            System.out.println("  Location: " + bucket.locationConstraint());
        }
    }
}

主要参考资料

使用存档层和对象还原

IBM Cloud Object Storage 提供归档存储类(Glacier),以较低的成本实现长期数据保留。 必须先恢复存档存储中的对象,然后才能访问它们。

将对象过渡到存档存储

您可以使用生命周期策略,在指定时间段后自动将对象过渡到存档存储。

public static void setArchiveRule(String bucketName, S3Client cosClient) {
    System.out.println("Setting archive rule on bucket: " + bucketName);

    // Create transition to Glacier after 30 days
    Transition transition = Transition.builder()
            .days(30)
            .storageClass(StorageClass.GLACIER)
            .build();

    // Create lifecycle rule
    LifecycleRuleFilter filter = LifecycleRuleFilter.builder()
            .prefix("archive/")
            .build();

    LifecycleRule rule = LifecycleRule.builder()
            .id("archive-rule")
            .filter(filter)
            .transitions(transition)
            .status(ExpirationStatus.ENABLED)
            .build();

    // Apply lifecycle configuration
    BucketLifecycleConfiguration config = BucketLifecycleConfiguration.builder()
            .rules(rule)
            .build();

    PutBucketLifecycleConfigurationRequest request = PutBucketLifecycleConfigurationRequest.builder()
            .bucket(bucketName)
            .lifecycleConfiguration(config)
            .build();

    cosClient.putBucketLifecycleConfiguration(request);

    System.out.println("Archive rule configured!");
}

恢复存档对象

必须先还原存档存储中的对象,然后才能下载。 您可以指定已还原副本的可用天数。

public static void restoreArchivedObject(String bucketName, String objectKey, int days, S3Client cosClient) {
    System.out.println("Restoring archived object: " + objectKey);

    // Create restore request with duration
    RestoreRequest restoreRequest = RestoreRequest.builder()
            .days(days)
            .glacierJobParameters(GlacierJobParameters.builder()
                    .tier(Tier.STANDARD)  // Options: STANDARD (12 hours), EXPEDITED (2 hours), BULK (5-12 hours)
                    .build())
            .build();

    RestoreObjectRequest request = RestoreObjectRequest.builder()
            .bucket(bucketName)
            .key(objectKey)
            .restoreRequest(restoreRequest)
            .build();

    cosClient.restoreObject(request);

    System.out.println("Restore initiated. Object will be available for " + days + " days once restored.");
}

检查恢复状态

public static void checkRestoreStatus(String bucketName, String objectKey, S3Client cosClient) {
    System.out.println("Checking restore status for: " + objectKey);

    HeadObjectRequest request = HeadObjectRequest.builder()
            .bucket(bucketName)
            .key(objectKey)
            .build();

    HeadObjectResponse response = cosClient.headObject(request);

    if (response.restore() != null) {
        System.out.println("Restore Status: " + response.restore());

        // Parse restore status
        String restoreStatus = response.restore();
        if (restoreStatus.contains("ongoing-request=\"true\"")) {
            System.out.println("Restoration in progress...");
        } else if (restoreStatus.contains("ongoing-request=\"false\"")) {
            System.out.println("Object has been restored and is available for download");
        }
    } else {
        System.out.println("Object is not archived or no restore in progress");
    }
}

加速档案检索

IBM Cloud Object Storage 支持加速存档检索,以更快地访问存档数据:

  • 加急:2 小时检索时间
  • 标准:3-5 小时检索时间(默认值)
  • 散装:5-12 小时检索时间(成本最低)
public static void restoreWithExpeditedRetrieval(String bucketName, String objectKey, S3Client cosClient) {
    System.out.println("Restoring with expedited retrieval: " + objectKey);

    RestoreRequest restoreRequest = RestoreRequest.builder()
            .days(1)
            .glacierJobParameters(GlacierJobParameters.builder()
                    .tier(Tier.EXPEDITED)  // 2-hour retrieval
                    .build())
            .build();

    RestoreObjectRequest request = RestoreObjectRequest.builder()
            .bucket(bucketName)
            .key(objectKey)
            .restoreRequest(restoreRequest)
            .build();

    cosClient.restoreObject(request);

    System.out.println("Expedited restore initiated (2-hour retrieval)");
}

主要参考资料

使用 CORS (跨源资源共享)

CORS 配置允许在一个域中运行的网络应用程序从另一个域访问 IBM Cloud Object Storage 中的资源。

在水桶上设置 CORS 配置

public static void setCorsConfiguration(String bucketName, S3Client cosClient) {
    System.out.println("Setting CORS configuration on bucket: " + bucketName);

    // Create CORS rule
    CORSRule corsRule = CORSRule.builder()
            .allowedMethods("GET", "PUT", "POST", "DELETE")
            .allowedOrigins("https://example.com")
            .allowedHeaders("*")
            .maxAgeSeconds(3000)
            .exposeHeaders("ETag", "x-amz-request-id")
            .build();

    // Create CORS configuration
    CORSConfiguration corsConfig = CORSConfiguration.builder()
            .corsRules(corsRule)
            .build();

    PutBucketCorsRequest request = PutBucketCorsRequest.builder()
            .bucket(bucketName)
            .corsConfiguration(corsConfig)
            .build();

    cosClient.putBucketCors(request);

    System.out.println("CORS configuration applied!");
}

获取 CORS 配置

public static void getCorsConfiguration(String bucketName, S3Client cosClient) {
    System.out.println("Getting CORS configuration for bucket: " + bucketName);

    GetBucketCorsRequest request = GetBucketCorsRequest.builder()
            .bucket(bucketName)
            .build();

    GetBucketCorsResponse response = cosClient.getBucketCors(request);

    System.out.println("CORS Rules:");
    for (CORSRule rule : response.corsRules()) {
        System.out.println("  Allowed Methods: " + rule.allowedMethods());
        System.out.println("  Allowed Origins: " + rule.allowedOrigins());
        System.out.println("  Allowed Headers: " + rule.allowedHeaders());
        System.out.println("  Max Age: " + rule.maxAgeSeconds());
    }
}

删除 CORS 配置

public static void deleteCorsConfiguration(String bucketName, S3Client cosClient) {
    System.out.println("Deleting CORS configuration from bucket: " + bucketName);

    DeleteBucketCorsRequest request = DeleteBucketCorsRequest.builder()
            .bucket(bucketName)
            .build();

    cosClient.deleteBucketCors(request);

    System.out.println("CORS configuration deleted!");
}

主要参考资料


使用水桶策略

存储桶策略为存储桶和对象提供访问控制管理。 它们以 JSON 格式编写,可以授予或拒绝授予用户和服务权限。

设置水桶政策

public static void setBucketPolicy(String bucketName, S3Client cosClient) {
    System.out.println("Setting bucket policy on: " + bucketName);

    // Create policy document (JSON format)
    String policyText = "{"
            + "\"Version\": \"2012-10-17\","
            + "\"Statement\": [{"
            + "  \"Effect\": \"Allow\","
            + "  \"Principal\": {\"AWS\": \"*\"},"
            + "  \"Action\": \"s3:GetObject\","
            + "  \"Resource\": \"arn:aws:s3:::" + bucketName + "/*\""
            + "}]"
            + "}";

    PutBucketPolicyRequest request = PutBucketPolicyRequest.builder()
            .bucket(bucketName)
            .policy(policyText)
            .build();

    cosClient.putBucketPolicy(request);

    System.out.println("Bucket policy applied!");
}

获取水桶政策

public static void getBucketPolicy(String bucketName, S3Client cosClient) {
    System.out.println("Getting bucket policy for: " + bucketName);

    GetBucketPolicyRequest request = GetBucketPolicyRequest.builder()
            .bucket(bucketName)
            .build();

    GetBucketPolicyResponse response = cosClient.getBucketPolicy(request);

    System.out.println("Policy: " + response.policy());
}

删除水桶策略

public static void deleteBucketPolicy(String bucketName, S3Client cosClient) {
    System.out.println("Deleting bucket policy from: " + bucketName);

    DeleteBucketPolicyRequest request = DeleteBucketPolicyRequest.builder()
            .bucket(bucketName)
            .build();

    cosClient.deleteBucketPolicy(request);

    System.out.println("Bucket policy deleted!");
}

主要参考资料


创建托管静态网站

IBM Cloud Object Storage 支持直接从桶托管静态网站。 您可以通过指定索引文档和错误文档来配置水桶,以便为静态内容提供服务。

该操作需要以下导入语句:

import com.ibm.cos.v2.services.s3.model.BucketWebsiteConfiguration;

设置水桶网站配置

此操作在配置后可提供以下功能,并需要正确配置的客户端:

  • 后缀桶配置 (索引文件)
  • 密钥桶配置 (错误文件)
public static void setBucketWebsiteConfiguration(String bucketName, S3Client cosClient) {
    System.out.println("Setting website configuration for bucket: " + bucketName);

    // Create website configuration with index and error documents
    IndexDocument indexDocument = IndexDocument.builder()
            .suffix("index.html")
            .build();

    ErrorDocument errorDocument = ErrorDocument.builder()
            .key("error.html")
            .build();

    WebsiteConfiguration websiteConfig = WebsiteConfiguration.builder()
            .indexDocument(indexDocument)
            .errorDocument(errorDocument)
            .build();

    PutBucketWebsiteRequest request = PutBucketWebsiteRequest.builder()
            .bucket(bucketName)
            .websiteConfiguration(websiteConfig)
            .build();

    cosClient.putBucketWebsite(request);

    System.out.println("Website configuration set successfully!");
}

获取水桶网站配置

public static void getBucketWebsiteConfiguration(String bucketName, S3Client cosClient) {
    System.out.println("Getting website configuration for bucket: " + bucketName);

    GetBucketWebsiteRequest request = GetBucketWebsiteRequest.builder()
            .bucket(bucketName)
            .build();

    GetBucketWebsiteResponse response = cosClient.getBucketWebsite(request);

    System.out.println("Index Document: " + response.indexDocument().suffix());
    System.out.println("Error Document: " + response.errorDocument().key());
}

删除水桶网站配置

public static void deleteBucketWebsiteConfiguration(String bucketName, S3Client cosClient) {
    System.out.println("Deleting website configuration from bucket: " + bucketName);

    DeleteBucketWebsiteRequest request = DeleteBucketWebsiteRequest.builder()
            .bucket(bucketName)
            .build();

    cosClient.deleteBucketWebsite(request);

    System.out.println("Website configuration deleted!");
}

主要参考资料

错误处理和最佳做法

处理 SDK 异常

v2 SDK 针对不同的错误情况使用特定的异常类型。

import com.ibm.cos.v2.services.s3.model.S3Exception;
import com.ibm.cos.v2.services.s3.model.NoSuchBucketException;
import com.ibm.cos.v2.services.s3.model.NoSuchKeyException;

public static void handleExceptions(String bucketName, String objectKey, S3Client cosClient) {
    try {
        GetObjectRequest request = GetObjectRequest.builder()
                .bucket(bucketName)
                .key(objectKey)
                .build();

        cosClient.getObject(request, ResponseTransformer.toBytes());

    } catch (NoSuchBucketException e) {
        System.err.println("Bucket does not exist: " + bucketName);
        System.err.println("Error Code: " + e.awsErrorDetails().errorCode());

    } catch (NoSuchKeyException e) {
        System.err.println("Object does not exist: " + objectKey);
        System.err.println("Error Code: " + e.awsErrorDetails().errorCode());

    } catch (S3Exception e) {
        System.err.println("S3 Error: " + e.awsErrorDetails().errorMessage());
        System.err.println("Error Code: " + e.awsErrorDetails().errorCode());
        System.err.println("Status Code: " + e.statusCode());

    } catch (Exception e) {
        System.err.println("Unexpected error: " + e.getMessage());
    }
}

v2 SDK 的最佳实践

  • 重复使用 S3Client 实例:创建客户端的成本很高。 在不同请求中重复使用它们。
// Good: Create once, reuse
S3Client client = S3Client.builder()
        .endpointOverride(URI.create(endpoint))
        .credentialsProvider(StaticCredentialsProvider.create(credentials))
        .region(Region.of(region))
        .build();

// Use client for multiple operations
client.listBuckets();
client.putObject(...);
client.getObject(...);

// Close when done
client.close();
  • 使用资源尝试:确保适当的资源清理。
try (S3Client client = S3Client.builder()
        .endpointOverride(URI.create(endpoint))
        .credentialsProvider(StaticCredentialsProvider.create(credentials))
        .region(Region.of(region))
        .build()) {

    // Perform operations
    client.listBuckets();

} // Client automatically closed
  • 使用多部分上传处理大文件:对于超过 5 MB 的文件,请使用多部分上传。

  • 使用传输管理器进行大型传输:提供自动多部分上传、重试逻辑和进度跟踪功能。

  • 设置适当的超时:根据使用情况配置客户端超时。

S3Client client = S3Client.builder()
        .endpointOverride(URI.create(endpoint))
        .credentialsProvider(StaticCredentialsProvider.create(credentials))
        .region(Region.of(region))
        .overrideConfiguration(ClientOverrideConfiguration.builder()
                .apiCallTimeout(Duration.ofMinutes(5))
                .apiCallAttemptTimeout(Duration.ofMinutes(2))
                .build())
        .build();

主要参考资料

其他资源

获取帮助

本文档提供了 IBM Cloud Object Storage Java SDK v2 的结构和 SDK 参考资料。 有关所有操作的完整工作代码示例,请参阅 GitHub 资源库中的 示例目录迁移指南