使用 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
  • 改良的串流:更好的串流 API,包含 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 金鑰及服務實例 ID),來建立及配置用戶端 cos。 這些值也可以自動從 credentials 檔案或環境變數中取得。

產生服務認證後,會將產生的 JSON 文件儲存為 ~/.bluemix/cos_credentials。 除非在建立用戶端期間,明確地設定其他認證,否則 SDK 將自動從此檔案讀取認證。 如果 cos_credentials 檔案包含 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);
}

主要參考資料

使用 Immutable Object Storage

使用者可以設定具有不變 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。
Retention-Expiration-Date 日期(ISO 8601 格式) 合法刪除或修改物件的日期。 您只能指定這個或 Retention-Period 標頭。 如果兩者都指定,將會傳回 400 錯誤。 如果未指定任一項,則會使用儲存區的 DefaultRetention 期間。
Retention-Legal-Hold-Id 字串 要套用至物件的單一合法保留。 合法保留是一個 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 或類似方法)

物件 meta 資料中所儲存的現行保留期間可透過給定的額外時間增加,或取代為新值,視 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!");
}

使用 Transfer Manager 上傳較大的物件

傳輸管理員提供簡單的 API,可將物件上傳或下載到 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();
    }
}

主要參考資料

更新 meta 資料

更新現有物件的元資料

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 配置允許在一個網域中執行的 Web 應用程式從另一個網域存取 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-with-resources:確保適當的資源清理。
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 的檔案,請使用多部分上傳。

  • 使用 Transfer Manager 進行大型傳輸:提供自動多部分上傳、重試邏輯和進度追蹤。

  • 設定適當的逾時時間:針對您的使用情況設定用戶端超時。

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 套件庫中的 範例目錄Migration Guide