使用 IBM Cloud® Object Storage Java SDK
支援將於 2027 年 8 月 6 日結束。 IBM Cloud® Object Storage (COS)SDK v1 將於 2027 年 8 月 6 日停止支援。 此日期之後,該產品將不再獲得更新、安全性修補程式或新版本。 我們建議您遷移至 IBM Cloud Object Storage SDK Java v2,該服務不僅提供更佳的效能、更強大的安全性與現代化的 API,還可持續獲得 IBM 的技術支援。
使用 IBM Cloud® Object Storage Java SDK 來建立客戶端、取得憑證、上傳大型物件,並透過 Key Protect 和 Aspera 管理儲存桶。
IBM Cloud Object Storage SDK for Java 包羅萬象,有許多特性和功能超出本手冊的描述範圍。 如需詳細的類別及方法文件,請參閱 Javadoc。 原始碼可以在 GitHub 儲存庫中找到。
取得 SDK
使用 IBM Cloud Object Storage Java SDK 最簡單的方法是使用 Maven 來管理相依關係。 如果您對 Maven 還不熟悉,可以參考《 5 分鐘 掌握 Maven》指南來快速上手。
Maven 會使用稱為 pom.xml 的檔案,來指定 Java 專案所需的程式庫(及其版本)。 以下是使用 IBM Cloud Object Storage Java SDK 連接至 Object Storage 的範例 pom.xml 檔。
<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>
<version>1.0.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.ibm.cos</groupId>
<artifactId>ibm-cos-java-sdk</artifactId>
<version>2.8.0</version>
</dependency>
</dependencies>
</project>
建立用戶端及讀取認證
在下列範例中,是透過提供認證資訊(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 會優先。
如需用戶端建構的詳細資料,請參閱 Javadoc。
程式碼範例
在程式碼中,您必須移除這裡提供的角括弧或任何其他多餘字元,以作為圖解。
讓我們先從一個完整範例類別開始,該類別將示範一些基本功能,接著再逐一探討各個類別。 此類 CosExample 別會列出現有儲存桶中的物件、建立新的儲存桶,然後列出該服務實例中的所有儲存桶。
收集必要資訊
bucketName及newBucketName是唯一且 DNS 安全的字串。 因為儲存區名稱在整個系統中是唯一的,因此如果此範例執行多次,將需要變更這些值。 請注意,名稱在刪除後會保留 10 到 15 分鐘。apiKey是 服務憑證 中以 形式呈現的值apikey。serviceInstanceId是 服務憑證 中以 形式呈現的值resource_instance_id。endpointUrl是一個服務端點 URL,包含 協定https://。 這並非服務憑證 中所包含的值endpoints。 如需端點的相關資訊,請參閱端點及儲存空間位置。storageClass是一個 有效的配置代碼,對應於 值endpoint。 然後,這會用來作為 S3 APILocationConstraint變數。location應該設定為storageClass的位置部分。 若為us-south-standard,這將是us-south。 此變數僅用於計算 HMAC 簽章,但任何用戶端(包括使用 IAM API 金鑰的這個範例)都需要此變數。
package com.cos;
import java.time.LocalDateTime;
import java.util.List;
import com.ibm.cloud.objectstorage.ClientConfiguration;
import com.ibm.cloud.objectstorage.auth.AWSCredentials;
import com.ibm.cloud.objectstorage.auth.AWSStaticCredentialsProvider;
import com.ibm.cloud.objectstorage.client.builder.AwsClientBuilder.EndpointConfiguration;
import com.ibm.cloud.objectstorage.services.s3.AmazonS3;
import com.ibm.cloud.objectstorage.services.s3.AmazonS3ClientBuilder;
import com.ibm.cloud.objectstorage.services.s3.model.Bucket;
import com.ibm.cloud.objectstorage.services.s3.model.ListObjectsRequest;
import com.ibm.cloud.objectstorage.services.s3.model.ObjectListing;
import com.ibm.cloud.objectstorage.services.s3.model.S3ObjectSummary;
import com.ibm.cloud.objectstorage.oauth.BasicIBMOAuthCredentials;
public class CosExample
{
public static void main(String[] args)
{
String bucketName = "<BUCKET_NAME>"; // eg my-unique-bucket-name
String newBucketName = "<NEW_BUCKET_NAME>"; // eg my-other-unique-bucket-name
String apiKey = "<API_KEY>"; // eg "W00YiRnLW4k3fTjMB-oiB-2ySfTrFBIQQWanc--P3byk"
String serviceInstanceId = "<SERVICE_INSTANCE_ID"; // eg "crn:v1:bluemix:public:cloud-object-storage:global:a/3bf0d9003abfb5d29761c3e97696b71c:d6f04d83-6c4f-4a62-a165-696756d63903::"
String endpointUrl = "https://s3.us-south.cloud-object-storage.appdomain.cloud"; // this could be any service endpoint
String storageClass = "us-south-standard";
String location = "us"; // not an endpoint, but used in a custom function below to obtain the correct URL
System.out.println("Current time: " + LocalDateTime.now());
AmazonS3 cosClient = createClient(apiKey, serviceInstanceId, endpointUrl, location);
listObjects(cosClient, bucketName);
createBucket(cosClient, newBucketName, storageClass);
listBuckets(cosClient);
}
public static AmazonS3 createClient(String apiKey, String serviceInstanceId, String endpointUrl, String location)
{
AWSCredentials credentials = new BasicIBMOAuthCredentials(apiKey, serviceInstanceId);
ClientConfiguration clientConfig = new ClientConfiguration()
.withRequestTimeout(5000)
.withTcpKeepAlive(true);
return AmazonS3ClientBuilder
.standard()
.withCredentials(new AWSStaticCredentialsProvider(credentials))
.withEndpointConfiguration(new EndpointConfiguration(endpointUrl, location))
.withPathStyleAccessEnabled(true)
.withClientConfiguration(clientConfig)
.build();
}
public static void listObjects(AmazonS3 cosClient, String bucketName)
{
System.out.println("Listing objects in bucket " + bucketName);
ObjectListing objectListing = cosClient.listObjects(new ListObjectsRequest().withBucketName(bucketName));
for (S3ObjectSummary objectSummary : objectListing.getObjectSummaries()) {
System.out.println(" - " + objectSummary.getKey() + " " + "(size = " + objectSummary.getSize() + ")");
}
System.out.println();
}
public static void createBucket(AmazonS3 cosClient, String bucketName, String storageClass)
{
cosClient.createBucket(bucketName, storageClass);
}
public static void listBuckets(AmazonS3 cosClient)
{
System.out.println("Listing buckets");
final List<Bucket> bucketList = cosClient.listBuckets();
for (final Bucket bucket : bucketList) {
System.out.println(bucket.getName());
}
System.out.println();
}
}
起始設定配置
private static String COS_ENDPOINT = "<endpoint>"; // eg "https://s3.us.cloud-object-storage.appdomain.cloud"
private static String COS_API_KEY_ID = "<api-key>"; // eg "0viPHOY7LbLNa9eLftrtHPpTjoGv6hbLD1QalRXikliJ"
private static String COS_AUTH_ENDPOINT = "https://iam.cloud.ibm.com/identity/token";
private static String COS_SERVICE_CRN = "<resource-instance-id>"; // "crn:v1:bluemix:public:cloud-object-storage:global:a/<CREDENTIAL_ID_AS_GENERATED>:<SERVICE_ID_AS_GENERATED>::"
private static String COS_BUCKET_LOCATION = "<location>"; // eg "us"
public static void main(String[] args)
{
SDKGlobalConfiguration.IAM_ENDPOINT = COS_AUTH_ENDPOINT;
try {
_cos = createClient(COS_API_KEY_ID, COS_SERVICE_CRN, COS_ENDPOINT, COS_BUCKET_LOCATION);
} catch (SdkClientException sdke) {
System.out.printf("SDK Error: %s\n", sdke.getMessage());
} catch (Exception e) {
System.out.printf("Error: %s\n", e.getMessage());
}
}
public static AmazonS3 createClient(String api_key, String service_instance_id, String endpoint_url, String location)
{
AWSCredentials credentials = new BasicIBMOAuthCredentials(api_key, service_instance_id);
ClientConfiguration clientConfig = new ClientConfiguration().withRequestTimeout(5000);
clientConfig.setUseTcpKeepAlive(true);
AmazonS3 cos = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(credentials))
.withEndpointConfiguration(new EndpointConfiguration(endpoint_url, location)).withPathStyleAccessEnabled(true)
.withClientConfiguration(clientConfig).build();
return cos;
}
金鑰值
<endpoint>- 您的雲端物件儲存( Object Storage )的公開端點(可從 IBM Cloud 儀表板取得)。 如需端點的相關資訊,請參閱端點及儲存空間位置。<api-key>- 建立服務憑證時所產生的 API 金鑰(建立與刪除範例需具備寫入權限)<resource-instance-id>- 您的雲端物件儲存( Object Storage )的資源 ID(可透過 IBM Cloud CLI 或 IBM Cloud 儀表板取得 )<location>- 雲端 Object Storage 的預設位置(必須與所使用的區域相符<endpoint>)
SDK 參照
類別
決定端點
下面的方法可用來根據儲存區位置、端點類型(公用或專用)及特定地區(選用)來決定服務端點。 如需端點的相關資訊,請參閱端點及儲存空間位置。
/**
* Returns a service endpoint based on the
* storage class location (i.e. us-standard, us-south-standard),
* endpoint type (public or private)
*/
public static String getEndpoint(String location, String endPointType) {
return getEndpoint(location, "", endPointType);
}
/**
* Returns a service endpoint based on the
* storage class location (i.e. us-standard, us-south-standard),
* specific region if desired (i.e. sanjose, amsterdam) - only use if you want a specific regional endpoint,
* endpoint type (public or private)
*/
public static String getEndpoint(String location, String region, String endpointType) {
HashMap locationMap = new HashMap<String, String>();
locationMap.put("us", "s3-api.us-geo");
locationMap.put("us-dallas", "s3-api.dal-us-geo");
locationMap.put("us-sanjose", "s3-api.sjc-us-geo");
locationMap.put("us-washington", "s3-api.wdc-us-geo");
locationMap.put("us-south", "s3.us-south");
locationMap.put("us-east", "s3.us-east");
locationMap.put("eu", "s3.eu-geo");
locationMap.put("eu-amsterdam", "s3.ams-eu-geo");
locationMap.put("eu-frankfurt", "s3.fra-eu-geo");
/** locationMap.put("eu-milan", "s3.mil-eu-geo");*/
locationMap.put("eu-gb", "s3.eu-gb");
locationMap.put("eu-germany", "s3.eu-de");
locationMap.put("ap", "s3.ap-geo");
locationMap.put("ap-tokyo", "s3.tok-ap-geo");
locationMap.put("che01", "s3.che01");
locationMap.put("mel01", "s3.mel01");
locationMap.put("tor01", "s3.tor01");
String key = location.substring(0, location.lastIndexOf("-")) + (region != null && !region.isEmpty() ? "-" + region : "");
String endpoint = locationMap.getOrDefault(key, null).toString();
if (endpoint != null) {
if (endpointType.toLowerCase() == "private")
endpoint += ".objectstorage.service.networklayer.com";
else
endpoint += ".objectstorage.s3.us-south.cloud-object-storage.appdomain.cloud.net";
}
return endpoint;
}
建立新的儲存區
public static void createBucket(String bucketName) {
System.out.printf("Creating new bucket: %s\n", bucketName);
_cos.createBucket(bucketName);
System.out.printf("Bucket: %s created!\n", bucketName);
}
建立具有不同儲存空間類別的儲存區
LocationConstraint 的有效佈建碼清單可以在儲存空間類別手冊中參閱。
cos.createBucket("sample", "us-vault"); // the name of the bucket, and the storage class (LocationConstraint)
SDK 參照
建立新的文字檔
public static void createTextFile(String bucketName, String itemName, String fileText) {
System.out.printf("Creating new item: %s\n", itemName);
byte[] arr = fileText.getBytes(StandardCharsets.UTF_8);
InputStream newStream = new ByteArrayInputStream(arr);
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(arr.length);
PutObjectRequest req = new PutObjectRequest(bucketName, itemName, newStream, metadata);
_cos.putObject(req);
System.out.printf("Item: %s created!\n", itemName);
}
請注意,在將自訂 meta 資料新增至物件時,必須使用 SDK 來建立 ObjectMetadata 物件,而不要手動傳送包含 x-amz-meta-{key} 的自訂標頭。 後者可能會在使用 HMAC 認證進行鑑別時造成問題。
從檔案上傳物件
此範例假設儲存區 sample 已存在。
cos.putObject(
"sample", // the name of the destination bucket
"myfile", // the object key
new File("/home/user/test.txt") // the file name and path of the object to be uploaded
);
使用串流上傳物件
此範例假設儲存區 sample 已存在。
String obj = "An example"; // the object to be stored
ByteArrayOutputStream theBytes = new ByteArrayOutputStream(); // create a new output stream to store the object data
ObjectOutputStream serializer = new ObjectOutputStream(theBytes); // set the object data to be serialized
serializer.writeObject(obj); // serialize the object data
serializer.flush();
serializer.close();
InputStream stream = new ByteArrayInputStream(theBytes.toByteArray()); // convert the serialized data to a new input stream to store
ObjectMetadata metadata = new ObjectMetadata(); // define the metadata
metadata.setContentType("application/x-java-serialized-object"); // set the metadata
metadata.setContentLength(theBytes.size()); // set metadata for the length of the data stream
cos.putObject(
"sample", // the name of the bucket to which the object is being written
"serialized-object", // the name of the object being written
stream, // the name of the data stream writing the object
metadata // the metadata for the object being written
);
或者,您可以使用 CipherInputStream 來更輕鬆地加密資料串流,而不需要超載現有的 InputStream 物件。
public CipherInputStream encryptStream(InputStream inputStream) {
// Generate key
KeyGenerator kgen = KeyGenerator.getInstance("AES");
kgen.init(128);
SecretKey aesKey = kgen.generateKey();
// Encrypt cipher
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, aesKey);
CipherInputStream cis = new CipherInputStream(inputStream, cipher);
return cis;
}
將物件下載至檔案
此範例假設儲存區 sample 已存在。
GetObjectRequest request = new // create a new request to get an object
GetObjectRequest( // request the new object by identifying
"sample", // the name of the bucket
"myFile" // the name of the object
);
s3Client.getObject( // write the contents of the object
request, // using the request that was just created
new File("retrieved.txt") // to write to a new file
);
使用串流下載物件
此範例假設儲存區 sample 已存在。
S3Object returned = cos.getObject( // request the object by identifying
"sample", // the name of the bucket
"serialized-object" // the name of the serialized object
);
S3ObjectInputStream s3Input = returned.getObjectContent(); // set the object stream
複製物件
// copy an object within the same Bucket
cos.copyObject( // copy the Object, passing…
"sample", // the name of the Bucket in which the Object to be copied is stored,
"myFile.txt", // the name of the Object being copied from the source Bucket,
"sample", // the name of the Bucket in which the Object to be copied is stored,
"myFile.txt.backup" // and the new name of the copy of the Object to be copied
);
// copy an object between two Buckets
cos.copyObject( // copy the Object, passing…
"sample", // the name of the Bucket from which the Object will be copied,
"myFile.txt", // the name of the Object being copied from the source Bucket,
"backup", // the name of the Bucket to which the Object will be copied,
"myFile.txt" // and the name of the copied Object in the destination Bucket
);
SDK 參照
類別
putObject 例外
即使新物件的上傳成功,此方法 putObject 仍可能拋出以下例外:
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException
at com.ibm.cloud.objectstorage.services.s3.AmazonS3Client.putObject(AmazonS3Client.java:1597)
at ibmcos.CoSExample.createTextFile(CoSExample.java:174)
at ibmcos.CoSExample.main(CoSExample.java:65)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBException
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:582)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:190)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:499)
... 3 more
**主要原因:**會將 JAXB API 視為 Java EE API,且不再包含在 Java SE 9 的預設類別路徑上。
**修正:**將下列項目新增至您專案資料夾中的 pom.xml 檔案,並重新包裝專案。
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.0</version>
</dependency>
列出可用的儲存區
public static void getBuckets() {
System.out.println("Retrieving list of buckets");
final List<Bucket> bucketList = _cos.listBuckets();
for (final Bucket bucket : bucketList) {
System.out.printf("Bucket Name: %s\n", bucket.getName());
}
}
SDK 參照
類別
方法
列出儲存區中的項目(第 2 版)
AmazonS3 物件包含用來列出內容的更新方法 (listObjectsV2)。 此方法可讓您限制傳回的記錄數,並分批次擷取記錄。 這可能有助於在應用程式內將您的結果進行分頁,並改善效能。
public static void getBucketContentsV2(String bucketName, int maxKeys) {
System.out.printf("Retrieving bucket contents (V2) from: %s\n", bucketName);
boolean moreResults = true;
String nextToken = "";
while (moreResults) {
ListObjectsV2Request request = new ListObjectsV2Request()
.withBucketName(bucketName)
.withMaxKeys(maxKeys)
.withContinuationToken(nextToken);
ListObjectsV2Result result = _cos.listObjectsV2(request);
for(S3ObjectSummary objectSummary : result.getObjectSummaries()) {
System.out.printf("Item: %s (%s bytes)\n", objectSummary.getKey(), objectSummary.getSize());
}
if (result.isTruncated()) {
nextToken = result.getNextContinuationToken();
System.out.println("...More results in next batch!\n");
}
else {
nextToken = "";
moreResults = false;
}
}
System.out.println("...No more results!");
}
SDK 參照
類別
方法
取得特定項目的檔案內容
public static void getItem(String bucketName, String itemName) {
System.out.printf("Retrieving item from bucket: %s, key: %s\n", bucketName, itemName);
S3Object item = _cos.getObject(new GetObjectRequest(bucketName, itemName));
try {
final int bufferSize = 1024;
final char[] buffer = new char[bufferSize];
final StringBuilder out = new StringBuilder();
InputStreamReader in = new InputStreamReader(item.getObjectContent());
for (; ; ) {
int rsz = in.read(buffer, 0, buffer.length);
if (rsz < 0)
break;
out.append(buffer, 0, rsz);
}
System.out.println(out.toString());
} catch (IOException ioe){
System.out.printf("Error reading file %s: %s\n", name, ioe.getMessage());
}
}
SDK 參照
類別
方法
從儲存區刪除項目
public static void deleteItem(String bucketName, String itemName) {
System.out.printf("Deleting item: %s\n", itemName);
_cos.deleteObject(bucketName, itemName);
System.out.printf("Item: %s deleted!\n", itemName);
}
SDK 參照
方法
從儲存區刪除多個項目
刪除要求最多可以包含您要刪除的 1000 個金鑰。 雖然這對於降低每次請求的效能損失非常有用,但在刪除大量金鑰時請務必謹慎。 此外,也請考量物件的大小,以確保適當的效能。
public static void deleteItems(String bucketName) {
DeleteObjectsRequest req = new DeleteObjectsRequest(bucketName);
req.withKeys(
"deletetest/testfile1.txt",
"deletetest/testfile2.txt",
"deletetest/testfile3.txt",
"deletetest/testfile4.txt",
"deletetest/testfile5.txt"
);
DeleteObjectsResult res = _cos.deleteObjects(req);
System.out.printf("Deleted items for %s\n", bucketName);
List<DeleteObjectsResult.DeletedObject> deletedItems = res.getDeletedObjects();
for(DeleteObjectsResult.DeletedObject deletedItem : deletedItems) {
System.out.printf("Deleted item: %s\n", deletedItem.getKey());
}
}
SDK 參照
類別
方法
刪除儲存區
public static void deleteBucket(String bucketName) {
System.out.printf("Deleting bucket: %s\n", bucketName);
_cos.deleteBucket(bucketName);
System.out.printf("Bucket: %s deleted!\n", bucketName);
}
SDK 參照
方法
檢查物件是否可公開讀取
public static void getItemACL(String bucketName, String itemName) {
System.out.printf("Retrieving ACL for %s from bucket: %s\n", itemName, bucketName);
AccessControlList acl = _cos.getObjectAcl(bucketName, itemName);
List<Grant> grants = acl.getGrantsAsList();
for (Grant grant : grants) {
System.out.printf("User: %s (%s)\n", grant.getGrantee().getIdentifier(), grant.getPermission().toString());
}
}
SDK 參照
類別
方法
執行多部分上傳
public static void multiPartUpload(String bucketName, String itemName, String filePath) {
File file = new File(filePath);
if (!file.isFile()) {
System.out.printf("The file '%s' does not exist or is not accessible.\n", filePath);
return;
}
System.out.printf("Starting multi-part upload for %s to bucket: %s\n", itemName, bucketName);
InitiateMultipartUploadResult mpResult = _cos.initiateMultipartUpload(new InitiateMultipartUploadRequest(bucketName, itemName));
String uploadID = mpResult.getUploadId();
//begin uploading the parts
//min 5MB part size
long partSize = 1024 * 1024 * 5;
long fileSize = file.length();
long partCount = ((long)Math.ceil(fileSize / partSize)) + 1;
List<PartETag> dataPacks = new ArrayList<PartETag>();
try {
long position = 0;
for (int partNum = 1; position < fileSize; partNum++) {
partSize = Math.min(partSize, (fileSize - position));
System.out.printf("Uploading to %s (part %s of %s)\n", name, partNum, partCount);
UploadPartRequest upRequest = new UploadPartRequest()
.withBucketName(bucketName)
.withKey(itemName)
.withUploadId(uploadID)
.withPartNumber(partNum)
.withFileOffset(position)
.withFile(file)
.withPartSize(partSize);
UploadPartResult upResult = _cos.uploadPart(upRequest);
dataPacks.add(upResult.getPartETag());
position += partSize;
}
//complete upload
_cos.completeMultipartUpload(new CompleteMultipartUploadRequest(bucketName, itemName, uploadID, dataPacks));
System.out.printf("Upload for %s Complete!\n", itemName);
} catch (SdkClientException sdke) {
System.out.printf("Multi-part upload aborted for %s\n", itemName);
System.out.printf("Upload Error: %s\n", sdke.getMessage());
_cos.abortMultipartUpload(new AbortMultipartUploadRequest(bucketName, itemName, uploadID));
}
}
SDK 參照
類別
- AbortMultipartUploadRequest
- CompleteMultipartUploadRequest
- InitiateMultipartUploadRequest
- InitiateMultipartUploadResult
- SdkClientException
- UploadPartRequest
- UploadPartResult
方法
建立備份政策
public static void main(String[] args) {
try {
// Initialize authenticator
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
// Initialize ResourceConfiguration client
ResourceConfiguration rcClient = new ResourceConfiguration("resource-configuration", authenticator);
// Generate unique backup vault name
String backupVaultName = "vault-" + UUID.randomUUID().toString();
// Create backup policy
CreateBackupPolicyOptions backupPolicyOptions = new CreateBackupPolicyOptions.Builder()
.bucket(SOURCE_BUCKET_NAME)
.initialRetention(new DeleteAfterDays.Builder().deleteAfterDays(1).build())
.policyName(BACKUP_POLICY_NAME)
.targetBackupVaultCrn(BACKUP_VAULT_CRN)
.backupType("continuous").build();
Response<BackupPolicy> createResult = rcClient.createBackupPolicy(backupPolicyOptions).execute();
System.out.println("Policy Name:");
System.out.println(createResult.getResult().getPolicyName());
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
列出備份政策
public static void main(String[] args) {
try {
// Initialize IAM authenticator and Resource Configuration client
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
ResourceConfiguration rcClient = new ResourceConfiguration("resource-configuration", authenticator);
// List all backup policies
ListBackupPoliciesOptions listOptions = new ListBackupPoliciesOptions.Builder()
.bucket(SOURCE_BUCKET_NAME)
.build();
Response<BackupPolicyCollection> listResponse = rcClient.listBackupPolicies(listOptions).execute();
System.out.println("\nList of backup policies:");
List<?> policies = listResponse.getResult().getBackupPolicies();
for (Object policy : policies) {
System.out.println(policy);
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
取得備份政策
public static void main(String[] args) {
try {
// Setup IAM Authenticator
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
// Initialize Resource Configuration client
ResourceConfiguration rcClient = new ResourceConfiguration("resource-configuration", authenticator);
// Generate unique policy name
String policyName = "policy_name_" + UUID.randomUUID().toString();
// Fetch backup policy using policy ID
GetBackupPolicyOptions getOptions = new GetBackupPolicyOptions.Builder()
.bucket(SOURCE_BUCKET_NAME)
.policyId(POLICY_ID)
.build();
Response<BackupPolicy> getResponse = rcClient.getBackupPolicy(getOptions).execute();
BackupPolicy fetchedPolicy = getResponse.getResult();
System.out.println("\nFetched Backup Policy Details:");
System.out.println(fetchedPolicy);
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
刪除備份原則
public static void main(String[] args) {
try {
// Setup IAM Authenticator
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
// Initialize Resource Configuration client
ResourceConfiguration rcClient = new ResourceConfiguration("resource-configuration", authenticator);
// Delete the created backup policy
DeleteBackupPolicyOptions deleteOptions = new DeleteBackupPolicyOptions.Builder()
.bucket(SOURCE_BUCKET_NAME)
.policyId(POLICY_ID)
.build();
rcClient.deleteBackupPolicy(deleteOptions).execute();
System.out.printf("Backup policy '%s' deleted successfully.%n", POLICY_ID);
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
建立備份儲存庫
public static void main(String[] args) {
try {
// Setup IAM Authenticator
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
// Initialize Resource Configuration client
ResourceConfiguration rcClient = new ResourceConfiguration("resource-configuration", authenticator);
// Generate unique backup vault name
String backupVaultName = "backup-vault-" + UUID.randomUUID();
// Create backup vault
CreateBackupVaultOptions createOptions = new CreateBackupVaultOptions.Builder()
.serviceInstanceId(SERVICE_INSTANCE_ID)
.backupVaultName(BACKUP_VAULT_NAME)
.region(REGION)
.build();
Response<BackupVault> response = rcClient.createBackupVault(createOptions).execute();
BackupVault vault = response.getResult();
System.out.println("Backup vault created:");
System.out.println(vault);
} catch (Exception e) {
System.err.println("Error creating backup vault: " + e.getMessage());
e.printStackTrace();
}
}
列出備份儲存庫
public static void main(String[] args) {
try {
// Setup IAM Authenticator
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
// Initialize Resource Configuration client
ResourceConfiguration rcClient = new ResourceConfiguration("resource-configuration", authenticator);
// List backup vaults
ListBackupVaultsOptions listBackupVaultsOptions = new ListBackupVaultsOptions.Builder().
serviceInstanceId(SERVICE_INSTANCE_ID).build();
Response<BackupVaultCollection> backupVaults = rcClient.listBackupVaults(listBackupVaultsOptions).execute();
System.out.println("\nList of backup vaults:");
if ( backupVaults.getResult().getBackupVaults() != null) {
for (String vault : backupVaults.getResult().getBackupVaults()) {
System.out.println(vault);
}
} else {
System.out.println("No backup vaults found.");
}
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
取得備份儲存庫
public static void main(String[] args) {
try {
// Initialize IAM Authenticator
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
// Create Resource Configuration client
ResourceConfiguration rcClient = new ResourceConfiguration("resource-configuration", authenticator);
// Generate unique backup vault name
String backupVaultName = "backup-vault-" + UUID.randomUUID();
// Get backup vault details
GetBackupVaultOptions getOptions = new GetBackupVaultOptions.Builder()
.backupVaultName(BACKUP_VAULT_NAME)
.build();
Response<BackupVault> getResponse = rcClient.getBackupVault(getOptions).execute();
BackupVault vaultDetails = getResponse.getResult();
System.out.println("Backup vault details:");
System.out.println(vaultDetails);
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
更新備份儲存庫
public static void main(String[] args) {
try {
// Setup IAM Authenticator
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
// Initialize Resource Configuration client
ResourceConfiguration rcClient = new ResourceConfiguration("resource-configuration", authenticator);
// Update vault: disable activity tracking and metrics monitoring
BackupVaultPatch backupVaultPatch = new BackupVaultPatch.Builder()
.activityTracking(new BackupVaultActivityTracking.Builder().managementEvents(Boolean.FALSE).build())
.metricsMonitoring(new BackupVaultMetricsMonitoring.Builder().usageMetricsEnabled(Boolean.FALSE).build())
.build();
UpdateBackupVaultOptions updateBackupVaultOptions = new UpdateBackupVaultOptions.Builder()
.backupVaultName(backupVaultName)
.backupVaultPatch(backupVaultPatch.asPatch()).build();
Response<BackupVault> backupVaultResponse2 = rcClient.updateBackupVault(updateBackupVaultOptions).execute();
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
刪除備份儲存庫
public static void main(String[] args) {
try {
// Set up the authenticator
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
// Initialize Resource Configuration client
ResourceConfiguration rcClient = new ResourceConfiguration("resource-configuration", authenticator);
// Delete backup vault
DeleteBackupVaultOptions deleteOptions = new DeleteBackupVaultOptions.Builder()
.backupVaultName(BACKUP_VAULT_NAME)
.build();
Response<Void> deleteResponse = rcClient.deleteBackupVault(deleteOptions).execute();
System.out.println("Failed to delete backup vault '" + BACKUP_VAULT_NAME + "'.");
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
列名復原範圍
public static void main(String[] args) {
try {
// Setup authenticator
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
// Initialize Resource Configuration client
ResourceConfiguration rcClient = new ResourceConfiguration("resource-configuration", authenticator);
// List recovery ranges
ListRecoveryRangesOptions recoveryRangesOptions = new ListRecoveryRangesOptions.Builder()
.backupVaultName(BACKUP_VAULT_NAME)
.build();
Response<RecoveryRangeCollection> recoveryRangesResponse = rcClient.listRecoveryRanges(recoveryRangesOptions).execute();
System.out.println("Recovery Ranges:");
System.out.println(recoveryRangesResponse.getResult());
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
取得復原範圍
public static void main(String[] args) {
try {
// Setup authenticator
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
// Initialize Resource Configuration client
ResourceConfiguration rcClient = new ResourceConfiguration("resource-configuration", authenticator);
// Fetch details of the recovery range
GetSourceResourceRecoveryRangeOptions recoveryRangeOptions = new GetSourceResourceRecoveryRangeOptions.Builder()
.backupVaultName(BACKUP_VAULT_NAME)
.recoveryRangeId(RECOVERY_RANGE_ID)
.build();
Response<RecoveryRange> getRecoveryRangeResponse = rcClient.getSourceResourceRecoveryRange(recoveryRangeOptions).execute();
System.out.println("Recovery Range Details:");
System.out.println(getRecoveryRangeResponse.getResult());
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
更新復原範圍
public static void main(String[] args) {
try {
// Setup authenticator
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
// Initialize Resource Configuration client
ResourceConfiguration rcClient = new ResourceConfiguration("resource-configuration", authenticator);
// Patch the recovery range (update retention to 99 days)
PatchSourceResourceRecoveryRangeOptions patchOptions = new PatchSourceResourceRecoveryRangeOptions.Builder()
.backupVaultName(BACKUP_VAULT_NAME)
.recoveryRangeId(RECOVERY_RANGE_ID)
.recoveryRangePatch(
new RecoveryRangePatch.Builder()
.retention(new DeleteAfterDays.Builder().deleteAfterDays(99).build())
.build()
)
.build();
Response<RecoveryRange> patchResponse = rcClient.patchSourceResourceRecoveryRange(patchOptions).execute();
System.out.println("Recovery Range successfully patched:");
System.out.println(patchResponse.getResult());
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
啟動還原
public static void main(String[] args) {
try {
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
ResourceConfiguration RC_CLIENT = new ResourceConfiguration("resource-configuration", authenticator);
CreateRestoreOptions createRestoreOptions = new CreateRestoreOptions.Builder()
.backupVaultName(BACKUP_VAULT_NAME)
.recoveryRangeId(recoveryRangeId)
.restoreType("in_place")
.targetResourceCrn(TARGET_BUCKET_CRN)
.restorePointInTime(RESTORE_TIME)
.build();
Response<Restore> createRestoreCall = RC_CLIENT.createRestore(createRestoreOptions).execute();
String restoreId = createRestoreCall.getResult().getRestoreId();
GetRestoreOptions getRestoreOptions = new GetRestoreOptions.Builder().restoreId(restoreId).backupVaultName(backupVaultName).build();
Response<Restore> restoreResult = RC_CLIENT.getRestore(getRestoreOptions).execute();
System.out.println("Restore successfully:");
System.out.println(restoreResult);
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
列名還原
public static void main(String[] args) {
try {
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
ResourceConfiguration RC_CLIENT = new ResourceConfiguration("resource-configuration", authenticator);
ListRestoresOptions listRestoreOptions = new ListRestoresOptions.Builder()
.backupVaultName(BACKUP_VAULT_NAME)
.build();
Response<RestoreList> listRestoreResponse = rcClient.listRestores(listRestoreOptions).execute();
System.out.println("Restore operations: " + listRestoreResponse.getResult());
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
取得還原詳細資訊
public static void main(String[] args) {
try {
IamAuthenticator authenticator = new IamAuthenticator.Builder()
.apikey(API_KEY)
.build();
ResourceConfiguration RC_CLIENT = new ResourceConfiguration("resource-configuration", authenticator);
Response<Restore> getRestoreOptions =
GetRestoreOptions.Builder()
.restoreId(restoreId)
.backupVaultName(BACKUP_VAULT_NAME)
.build();
Response<Restore> restoreResult = RC_CLIENT.getRestore(getRestoreOptions).execute();
System.out.println("Get Restore: " + restoreResult);
} catch (Exception e) {
System.err.println("Error: " + e.getMessage());
e.printStackTrace();
}
}
建立一個啟用物件鎖定功能的新 cos 儲存桶
public static void createBucket(String bucketName, AmazonS3 _cosClient)
{
_cosClient.createBucket(bucketName);
System.out.printf("Bucket: %s created!\n", bucketName);
}
在 Object Storage 儲存桶上設定符合合規模式的物件鎖定配置
public static void putObjectLockConfiguration(String bucketName, AmazonS3 _cosClient)
{
DefaultRetention defRet = new DefaultRetention()
.withMode(ObjectLockRetentionMode.COMPLIANCE)
.withDays(1);
ObjectLockRule objRule = new ObjectLockRule()
.withDefaultRetention(defRet);
ObjectLockConfiguration objConfig = new ObjectLockConfiguration()
.withObjectLockEnabled(ObjectLockEnabled.ENABLED)
.withRule(objRule);
SetObjectLockConfigurationRequest objSet = new SetObjectLockConfigurationRequest()
.withBucketName(BUCKET_NAME)
.withObjectLockConfiguration(objConfig);
_cosClient.setObjectLockConfiguration(objSet);
System.out.printf("Successfully added object lock cofiguration on : %s\n", bucketName);
}
在 Object Storage 儲存桶上設定具備治理模式的物件鎖定配置
public static void putObjectLockConfigurationWithGovernanceMode(String bucketName, AmazonS3 _cosClient)
{
DefaultRetention defRet = new DefaultRetention()
.withMode(ObjectLockRetentionMode.GOVERNANCE)
.withDays(1);
ObjectLockRule objRule = new ObjectLockRule()
.withDefaultRetention(defRet);
ObjectLockConfiguration objConfig = new ObjectLockConfiguration()
.withObjectLockEnabled(ObjectLockEnabled.ENABLED)
.withRule(objRule);
SetObjectLockConfigurationRequest objSet = new SetObjectLockConfigurationRequest()
.withBucketName(BUCKET_NAME)
.withObjectLockConfiguration(objConfig);
_cosClient.setObjectLockConfiguration(objSet);
System.out.printf("Successfully added object lock cofiguration on : %s\n", bucketName);
}
取得 Object Storage 儲存桶的物件鎖定設定
public static void getObjectLockConfigurationWithGovernanceMode(String bucketName, AmazonS3 _cosClient)
{
GetObjectLockConfigurationRequest objReq = new GetObjectLockConfigurationRequest().withBucketName(BUCKET_NAME);
GetObjectLockConfigurationResult objRes = _cosClient.getObjectLockConfiguration(objReq);
ObjectLockConfiguration objLckConfig = objRes.getObjectLockConfiguration();
ObjectLockRule objGetRule = objLckConfig.getRule();
System.out.printf("ObjectLock Configuration : %s\n", objGetRule);
}
將具有治理模式的物件上傳至 Object Storage 儲存桶
public static void uploadFileWithGovernanceMode(String bucketName, String itemName, String fileText) {
System.out.printf("Creating new item: %s\n", itemName);
LocalDate date = LocalDate.of(2025, 11, 11);
InputStream newStream = new ByteArrayInputStream(fileText.getBytes(Charset.forName("UTF-8")));
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(fileText.length());
PutObjectRequest req = new PutObjectRequest(bucketName, itemName, newStream, metadata)
.withObjectLockMode("GOVERNANCE")
.withObjectLockRetainUntilDate(date);
_cosClient.putObject(req);
System.out.printf("Item: %s created!\n", itemName);
}
在物件上啟用物件鎖保留與合規模式
public static void putObjectLockRetention(String bucketName,String itemName, AmazonS3 _cosClient)
{
LocalDate date = LocalDate.of(2025, 11, 11);
ObjectLockRetention objRet = new ObjectLockRetention()
.withMode("COMPLIANCE")
.withRetainUntilDate(date);
SetObjectRetentionRequest objSet = new SetObjectRetentionRequest()
.withBucketName(BUCKET_NAME)
.withitemName(itemName)
.withRetention(objRet);
.withBypassGovernanceRetention(true);
_cosClient.setObjectRetention(objSet);
System.out.printf("Successfully added object retention on : %s\n", itemName);
}
在物件上啟用物件鎖保留與治理模式
public static void putObjectLockRetentionWithGovernanceMode(String bucketName,String itemName, AmazonS3 _cosClient)
{
LocalDate date = LocalDate.of(2025, 11, 11);
ObjectLockRetention objRet = new ObjectLockRetention()
.withMode("GOVERNANCE")
.withRetainUntilDate(date);
SetObjectRetentionRequest objSet = new SetObjectRetentionRequest()
.withBucketName(BUCKET_NAME)
.withitemName(itemName)
.withRetention(objRet);
.withBypassGovernanceRetention(true);
_cosClient.setObjectRetention(objSet);
System.out.printf("Successfully added object retention on : %s\n", itemName);
}
取得物件鎖保留
public static void getObjectLockRetentionWithGovernanceMode(String bucketName,String itemName, AmazonS3 _cosClient)
{
GetObjectRetentionRequest objReq = new GetObjectRetentionRequest()
.withBucketName(BUCKET_NAME)
.withitemName(itemName);
GetObjectRetentionResult objRes1 = _cosClient.getObjectRetention(objReq);
ObjectLockRetention objRet1 = objRes1.getRetention();
System.out.printf("Retention : %s\n", objRet1);
}
將物件鎖定為法律保留狀態
public static void putObjectLockLegalHold(String bucketName,string itemName, AmazonS3 _cosClient)
{
ObjectLockLegalHold objLegalHold = new ObjectLockLegalHold()
.withStatus("ON");
SetObjectLegalHoldRequest objSetLegalHold = new SetObjectLegalHoldRequest()
.withBucketName(bucketName)
.withKey(itemName)
.withLegalHold(objLegalHold);
_cosClient.setObjectLegalHold(objSetLegalHold);
System.out.printf("Successfully added object lock legal hold on : %s\n", itemName);
GetObjectLegalHoldRequest objReqLegal = new GetObjectLegalHoldRequest()
.withBucketName(bucketName)
.withKey(itemName);
GetObjectLegalHoldResult objResLegal = _cosClient.getObjectLegalHold(objReqLegal);
System.out.printf("ObjectLock Legal Hold : %s\n", objResLegal.getLegalHold());
}
取得物件鎖定法律保留
public static void getObjectLockLegalHold(String bucketName,string itemName, AmazonS3 _cosClient)
{
GetObjectLegalHoldRequest objReqLegal = new GetObjectLegalHoldRequest()
.withBucketName(bucketName)
.withKey(itemName);
GetObjectLegalHoldResult objResLegal = _cosClient.getObjectLegalHold(objReqLegal);
System.out.printf("ObjectLock Legal Hold : %s\n", objResLegal.getLegalHold());
}
使用繞過治理刪除具有物件鎖治理模式的物件
public static void deleteObjectWithBypassGovernance(String bucketName, String itemName) {
System.out.printf("Deleting item: %s\n", itemName);
DeleteObjectRequest deleteRequest = new DeleteObjectRequest(BUCKET_NAME, Key)
.withBypassGovernanceRetention(true);
_cosClient.deleteObject(deleteRequest);
System.out.printf("Item: %s deleted!\n", itemName);
}
使用 Transfer Manager 上傳較大的物件
TransferManager 可簡化大型檔案傳送,方法是在必須設定配置參數時自動併入多部分上傳。
public static void largeObjectUpload(String bucketName, String itemName, String filePath) throws IOException, InterruptedException {
File uploadFile = new File(filePath);
if (!uploadFile.isFile()) {
System.out.printf("The file '%s' does not exist or is not accessible.\n", filePath);
return;
}
System.out.println("Starting large file upload with TransferManager");
//set the part size to 5 MB
long partSize = 1024 * 1024 * 5;
//set the threshold size to 5 MB
long thresholdSize = 1024 * 1024 * 5;
String endPoint = getEndpoint(COS_BUCKET_LOCATION, "public");
AmazonS3 s3client = createClient(COS_API_KEY_ID, COS_SERVICE_CRN, endPoint, COS_BUCKET_LOCATION);
TransferManager transferManager = TransferManagerBuilder.standard()
.withS3Client(s3client)
.withMinimumUploadPartSize(partSize)
.withMultipartCopyThreshold(thresholdSize)
.build();
try {
Upload lrgUpload = transferManager.upload(bucketName, itemName, uploadFile);
lrgUpload.waitForCompletion();
System.out.println("Large file upload complete!");
}
catch (SdkClientException e) {
System.out.printf("Upload error: %s\n", e.getMessage());
}
finally {
transferManager.shutdownNow();
}
SDK 參照
類別
方法
使用 Key Protect
Key Protect 可新增至儲存空間儲存區,以加密雲端中靜止的機密資料。
開始之前
若要建立啟用 Key-Protect 的儲存桶,需具備以下項目:
擷取根金鑰 CRN
- 擷取 Key Protect 服務的實例 ID
- 使用 Key Protect API 來擷取所有可用金鑰
- 您可以使用
curl指令或 API REST 用戶端(例如 Postman)來存取 Key Protect API。
- 您可以使用
- 檢索您用於在儲存桶上啟用 Key Protect 功能的根金鑰之 CRN。 CRN 的格式類似於以下範例:
crn:v1:bluemix:public:kms:us-south:a/3d624cd74a0dea86ed8efe3101341742:90b6a1db-0fe1-4fe9-b91e-962c327df531:key:0bg3e33e-a866-50f2-b715-5cba2bc93234
建立儲存區並啟用 key-protect
private static String COS_KP_ALGORITHM = "<algorithm>";
private static String COS_KP_ROOTKEY_CRN = "<root-key-crn>";
public static void createBucketKP(String bucketName) {
System.out.printf("Creating new encrypted bucket: %s\n", bucketName);
EncryptionType encType = new EncryptionType();
encType.setKmsEncryptionAlgorithm(COS_KP_ALGORITHM);
encType.setIBMSSEKMSCustomerRootKeyCrn(COS_KP_ROOTKEY_CRN);
CreateBucketRequest req = new CreateBucketRequest(bucketName).withEncryptionType(encType);
_cos.createBucket(req);
System.out.printf("Bucket: %s created!", bucketName);
}
金鑰值
<algorithm>- 新增至儲存桶的物件所使用的加密演算法(預設為 AES256 )。<root-key-crn>- 從 Key Protect 服務取得的根金鑰 (Root Key) 的 CRN。
SDK 參照
類別
方法
Key Protect 的新標頭
其他標頭已定義在 Headers 類別內:
public static final String IBM_SSE_KP_ENCRYPTION_ALGORITHM = "ibm-sse-kp-encryption-algorithm";
public static final String IBM_SSE_KP_CUSTOMER_ROOT_KEY_CRN = "ibm-sse-kp-customer-root-key-crn";
在建立儲存桶實作的同一個區段中,除了已新增 IAM 服務實例標頭外,還新增了 2 個加密標頭:
//Add IBM Service Instance Id & Encryption to headers
if ((null != this.awsCredentialsProvider ) && (this.awsCredentialsProvider.getCredentials() instanceof IBMOAuthCredentials)) {
IBMOAuthCredentials oAuthCreds = (IBMOAuthCredentials)this.awsCredentialsProvider.getCredentials();
if (oAuthCreds.getServiceInstanceId() != null) {
request.addHeader(Headers.IBM_SERVICE_INSTANCE_ID, oAuthCreds.getServiceInstanceId());
request.addHeader(Headers.IBM_SSE_KP_ENCRYPTION_ALGORITHM, createBucketRequest.getEncryptionType().getKpEncryptionAlgorithm());
request.addHeader(Headers.IBM_SSE_KP_CUSTOMER_ROOT_KEY_CRN, createBucketRequest.getEncryptionType().getIBMSSEKPCustomerRootKeyCrn());
}
}
已更新 和 ObjectListing HeadBucketResult 物件,新增包含布林型 及 IBMSSEKPEnabled 字串型 IBMSSEKPCustomerRootKeyCrn 變數,並附帶 getter 與 setter 方法。 这些会储存新标头的值。
GET 儲存區
public ObjectListing listObjects(String bucketName)
public ObjectListing listObjects(String bucketName, String prefix)
public ObjectListing listObjects(ListObjectsRequest listObjectsRequest)
該 ObjectListing 類別需要 2 個額外的方法:
ObjectListing listing = s3client.listObjects(listObjectsRequest)
String KPEnabled = listing.getIBMSSEKPEnabled();
String crkId = listing.getIBMSSEKPCrkId();
額外的標題已在 Headers 類別中定義:
Headers.java
public static final string IBM_SSE_KP_ENABLED = "ibm-sse-kp-enabled";
public static final String IBM_SSE_KP_CUSTOMER_ROOT_KEY_CRN = "ibm-sse-kp-customer-root-key-crn";
S3XmlResponseHandler 負責取消配置所有 XML 回應。 已新增一項檢查,確保結果為 的實例,ObjectListing 且檢索到的標頭已新增至 物件 ObjectListing 中:
if (result instanceof ObjectListing) {
if (!StringUtils.isNullOrEmpty(responseHeaders.get(Headers.IBM_SSE_KP_ENABLED)){
((ObjectListing) result).setIBMSSEKPEnabled(Boolean.parseBoolean(responseHeaders.get(Headers.IBM_SSE_KP_ENABLED)));
}
if (!StringUtils.isNullOrEmpty(responseHeaders.get(Headers.IBM_SSE_KP_CUSTOMER_ROOT_KEY_CRN))) {
((ObjectListing) result).setIBMSSEKPCrk(responseHeaders.get(Headers.IBM_SSE_KP_CUSTOMER_ROOT_KEY_CRN));
}
}
HEAD 儲存區
其他標頭已定義在 Headers 類別內:
Headers.java
public static final String IBM_SSE_KP_ENABLED = "ibm-sse-kp-enabled";
public static final String IBM_SSE_KP_CUSTOMER_ROOT_KEY_CRN = "ibm-sse-kp-customer-root-key-crn";
這些變數會移入 HeadBucketResponseHandler 中。
HeadBucketResultHandler
result.setIBMSSEKPEnabled(response.getHeaders().get(Headers.IBM_SSE_KP_ENABLED));
result.setIBMSSEKPCrk(response.getHeaders().get(Headers. IBM_SSE_KP_CUSTOMER_ROOT_KEY_CRN));
Head Bucket Example
HeadBucketResult result = s3client.headBucket(headBucketRequest)
boolean KPEnabled = result.getIBMSSEKPEnabled();
String crn = result.getIBMSSEKPCUSTOMERROOTKEYCRN();
使用 Aspera 高速傳輸
透過安裝 Aspera 高速傳輸函式庫,您即可在應用程式中使用高速檔案傳輸功能。 Aspera 函式庫為閉源軟體,因此是 Object Storage SDK(採用 Apache 授權)的可選依賴項。
每一個 Aspera 高速傳送階段作業都會產生在用戶端機器上執行的個別 ascp 處理程序,以執行傳送。 請確定您的運算環境可以容許執行此處理程序。
您需要建立 S3 Client 和 IAM Token Manager 類別的實例,以初始化該功能 AsperaTransferManager。 必須 s3Client 使用 才能取得目標儲存桶 Object Storage 的 FASP 連線資訊。 必須 tokenManager 提供此 Aspera 高速傳輸 SDK 才能對 Object Storage 目標儲存桶進行身份驗證。
起始設定 AsperaTransferManager
在起始設定 AsperaTransferManager 之前,請確定您已使用 s3Client 及 tokenManager 物件。
使用 AsperaTransferManagerBuilder 建置 AsperaTransferManager 時,建議使用 TokenManager tokenManager = new DefaultTokenManager(new DelegateTokenProvider(apiKey)); 並避免使用 .withTokenManager(tokenManager)。
除非您預期在網路中看到大量的雜訊或封包流失,否則使用 Aspera 高速傳送的單一階段作業不會有多大的好處。 因此,我們需要告知 AsperaTransferManager 使用 AsperaConfig 類別,以使用多個階段作業。 此機制將傳輸過程拆分為多個並行會話,各會話傳送的資料塊大小由閾值決定。
使用多個階段作業的一般配置應該是:
- 2500 MBps 目標率
- 100 MB 臨界值(此為大部分應用程式的建議值)
AsperaTransferManagerConfig transferConfig = new AsperaTransferManagerConfig()
.withMultiSession(true);
AsperaConfig asperaConfig = new AsperaConfig()
.withTargetRateMbps(2500L)
.withMultiSessionThresholdMb(100);
TokenManager tokenManager = new DefaultTokenManager(new DelegateTokenProvider(API_KEY));
AsperaTransferManager asperaTransferMgr = new AsperaTransferManagerBuilder(API_KEY, s3Client)
.withAsperaTransferManagerConfig(transferConfig)
.withAsperaConfig(asperaConfig)
.build();
在上述範例中,SDK 會大量產生足夠的階段作業,以嘗試達到目標率 2500 MBps。
或者,可以在 SDK 中明確配置階段作業管理。 在需要更精確控制網路使用率的情況下,這十分有用。
使用明確的多個階段作業的一般配置應該是:
- 2 或 10 個階段作業
- 100 MB 臨界值(此為大部分應用程式的建議值)
AsperaConfig asperaConfig = new AsperaConfig()
.withMultiSession(2)
.withMultiSessionThresholdMb(100);
TokenManager tokenManager = new DefaultTokenManager(new DelegateTokenProvider(API_KEY));
AsperaTransferManager asperaTransferMgr = new AsperaTransferManagerBuilder(API_KEY, s3Client)
.withAsperaConfig(asperaConfig)
.build();
為了在大多數情境下獲得最佳效能,請務必使用多個工作階段,以將建立 Aspera 高速傳輸實例所涉及的處理作業降至最低。 如果您的網路容量至少為 1 Gbps,您應該使用 10 個階段作業。 較低頻寬的網路應該使用兩個階段作業。
金鑰值
API_KEY- 具有「撰寫者」或「管理者」角色之使用者或服務 ID 的 API 金鑰
您需要提供一個 IAM API 金鑰,以便建立一個 AsperaTransferManager. 目前 不 支援 HMAC 認證。
如需 IAM 的相關資訊,請按一下這裡。
檔案上傳
String filePath = "<absolute-path-to-source-data>";
String bucketName = "<bucket-name>";
String itemName = "<item-name>";
// Load file
File inputFile = new File(filePath);
// Create AsperaTransferManager for FASP upload
AsperaTransferManager asperaTransferMgr = new AsperaTransferManagerBuilder(API_KEY, s3Client).build();
// Upload test file and report progress
Future<AsperaTransaction> asperaTransactionFuture = asperaTransferMgr.upload(bucketName, itemName, inputFile);
AsperaTransaction asperaTransaction = asperaTransactionFuture.get();
金鑰值
<bucket-name>- 您在已启用 Aspera 的 Object Storage 服务实例中,该存储桶的名称。<absolute-path-to-source-data>- 將上傳至 Object Storage 的目錄與檔案名稱。<item-name>- 新增至儲存桶中的新物件名稱。
檔案下載
String bucketName = "<bucket-name>";
String outputPath = "<absolute-path-to-file>";
String itemName = "<item-name>";
// Create local file
File outputFile = new File(outputPath);
outputFile.createNewFile();
// Create AsperaTransferManager for FASP download
AsperaTransferManager asperaTransferMgr = new AsperaTransferManagerBuilder(COS_API_KEY_ID, s3Client)
.withTokenManager(tokenManager)
.withAsperaConfig(asperaConfig)
.build();
// Download file
Future<AsperaTransaction> asperaTransactionFuture = asperaTransferMgr.download(bucketName, itemName, outputPath);
AsperaTransaction asperaTransaction = asperaTransactionFuture.get();
金鑰值
<bucket-name>- 您在已启用 Aspera 的 Object Storage 服务实例中,该存储桶的名称。<absolute-path-to-file>- 從 Object Storage 儲存的目錄及檔案名稱。<item-name>- 儲存桶中物件的名稱。
目錄上傳
String bucketName = "<bucket-name>";
String directoryPath = "<absolute-path-to-directory-for-new-file>";
String directoryPrefix = "<virtual-directory-prefix>";
boolean includeSubDirectories = true;
// Load Directory
File inputDirectory = new File(directoryPath);
// Create AsperaTransferManager for FASP upload
AsperaTransferManager asperaTransferMgr = new AsperaTransferManagerBuilder(COS_API_KEY_ID, s3Client)
.withTokenManager(tokenManager)
.withAsperaConfig(asperaConfig)
.build();
// Upload test directory
Future<AsperaTransaction> asperaTransactionFuture = asperaTransferMgr.uploadDirectory(bucketName, directoryPrefix, inputDirectory, includeSubDirectories);
AsperaTransaction asperaTransaction = asperaTransactionFuture.get();
金鑰值
<bucket-name>- 您在已启用 Aspera 的 Object Storage 服务实例中,该存储桶的名称。<absolute-path-to-directory>- 將上傳至 Object Storage 的檔案目錄。<virtual-directory-prefix>- 上傳時將附加至每個檔案的目錄前綴名稱。 請使用空值或空字串,將檔案上傳至儲存區根目錄。
目錄下載
String bucketName = "<bucket-name>";
String directoryPath = "<absolute-path-to-directory>";
String directoryPrefix = "<virtual-directory-prefix>";
boolean includeSubDirectories = true;
// Load Directory
File outputDirectory = new File(directoryPath);
// Create AsperaTransferManager for FASP download
AsperaTransferManager asperaTransferMgr = new AsperaTransferManagerBuilder(COS_API_KEY_ID, s3Client)
.withTokenManager(tokenManager)
.withAsperaConfig(asperaConfig)
.build();
// Download test directory
Future<AsperaTransaction> asperaTransactionFuture = asperaTransferMgr.downloadDirectory(bucketName, directoryPrefix, outputDirectory, includeSubDirectories);
AsperaTransaction asperaTransaction = asperaTransactionFuture.get();
金鑰值
<bucket-name>- 您在已启用 Aspera 的 Object Storage 服务实例中,该存储桶的名称。<absolute-path-to-directory>- 用於儲存從 Object Storage 下載的檔案的目錄。<virtual-directory-prefix>- 每個待下載檔案的目錄前綴名稱。 請使用空值或空字串,以下載儲存區中的所有檔案。
在每個傳送基礎上置換階段作業配置
在每個傳送基礎上,您可以透過將 AsperaConfig 的實例傳遞至上傳及下載已置換方法,來置換多階段作業配置值。 使用 AsperaConfig,您可以指定階段作業數及每個階段作業的檔案臨界值大小下限。
String bucketName = "<bucket-name>";
String filePath = "<absolute-path-to-file>";
String itemName = "<item-name>";
// Load file
File inputFile = new File(filePath);
// Create AsperaTransferManager for FASP upload
AsperaTransferManager asperaTransferMgr = new AsperaTransferManagerBuilder(API_KEY, s3Client)
.withTokenManager(TOKEN_MANAGER)
.withAsperaConfig(asperaConfig)
.build();
// Create AsperaConfig to set number of sessions
// and file threshold per session.
AsperaConfig asperaConfig = new AsperaConfig().
withMultiSession(10).
withMultiSessionThresholdMb(100);
// Upload test file and report progress
Future<AsperaTransaction> asperaTransactionFuture = asperaTransferMgr.upload(bucketName, itemName, inputFile, asperaConfig, null);
AsperaTransaction asperaTransaction = asperaTransactionFuture.get();
監視傳送進度
監視檔案/目錄傳送進度的最簡單方式是使用 isDone() 內容,當您的傳送完成時,會傳回 true。
Future<AsperaTransaction> asperaTransactionFuture = asperaTransferMgr.downloadDirectory(bucketName, directoryPrefix, outputDirectory, includeSubDirectories);
AsperaTransaction asperaTransaction = asperaTransactionFuture.get();
while (!asperaTransaction.isDone()) {
System.out.println("Directory download is in progress");
//pause for 3 seconds
Thread.sleep(1000 * 3);
}
您也可以透過在 上呼叫 方法 onQueue,來檢查轉帳是否已排入處理佇列 AsperaTransaction。該方法會 onQueue 傳回一個布林值,若為,則 true 表示該筆轉帳已排入佇列。
Future<AsperaTransaction> asperaTransactionFuture = asperaTransferMgr.downloadDirectory(bucketName, directoryPrefix, outputDirectory, includeSubDirectories);
AsperaTransaction asperaTransaction = asperaTransactionFuture.get();
while (!asperaTransaction.isDone()) {
System.out.println("Directory download is in queueing: " + asperaTransaction.onQueue());
//pause for 3 seconds
Thread.sleep(1000 * 3);
}
若要檢查傳送是否正在進行,請在 AsperaTransaction 中呼叫進度方法。
Future<AsperaTransaction> asperaTransactionFuture = asperaTransferMgr.downloadDirectory(bucketName, directoryPrefix, outputDirectory, includeSubDirectories);
AsperaTransaction asperaTransaction = asperaTransactionFuture.get();
while (!asperaTransaction.isDone()) {
System.out.println("Directory download is in progress: " + asperaTransaction.progress());
//pause for 3 seconds
Thread.sleep(1000 * 3);
}
預設情況下,每次傳輸都會 TransferProgress 附帶一個。 該報告會 TransferProgress 顯示已傳輸的位元組數,以及相對於總傳輸位元組數的傳輸百分比。 若要存取傳送的 TransferProgress,請在 getProgress 中使用 AsperaTransaction 方法。
Future<AsperaTransaction> asperaTransactionFuture = asperaTransferMgr.downloadDirectory(bucketName, directoryPrefix, outputDirectory, includeSubDirectories);
AsperaTransaction asperaTransaction = asperaTransactionFuture.get();
while (!asperaTransaction.isDone()) {
TransferProgress transferProgress = asperaTransaction.getProgress();
//pause for 3 seconds
Thread.sleep(1000 * 3);
}
若要報告傳送的位元組數,請在 getBytesTransferred上呼叫 TransferProgress 方法。 若要報告傳送的位元組總數傳送百分比,請在 getPercentTransferred 上呼叫 TransferProgress 方法。
Future<AsperaTransaction> asperaTransactionFuture = asperaTransferMgr.downloadDirectory(bucketName, directoryPrefix, outputDirectory, includeSubDirectories);
AsperaTransaction asperaTransaction = asperaTransactionFuture.get();
while (!asperaTransaction.isDone()) {
TransferProgress transferProgress = asperaTransaction.getProgress();
System.out.println("Bytes transferred: " + transferProgress.getBytesTransferred());
System.out.println("Percent transferred: " + transferProgress.getPercentTransferred());
//pause for 3 seconds
Thread.sleep(1000 * 3);
}
暫停/繼續/取消
SDK 可讓您透過 AsperaTransfer 物件的下列方法來管理檔案/目錄傳送的進度:
pause()resume()cancel()
呼叫上述任一種方法時,不會產生任何副作用。 SDK 會處理適當的清除及整理。
下列範例顯示這些方法的可能用法:
String bucketName = "<bucket-name>";
String directoryPath = "<absolute-path-to-directory>";
String directoryPrefix = "<virtual-directory-prefix>";
boolean includeSubDirectories = true;
AsperaTransferManager asperaTransferMgr = new AsperaTransferManagerBuilder(COS_API_KEY_ID, _cos)
.withTokenManager(TOKEN_MANAGER)
.build();
File outputDirectory = new File(directoryName);
System.out.println("Starting directory download...");
//download the directory from cloud storage
Future<AsperaTransaction> asperaTransactionFuture = asperaTransferMgr.downloadDirectory(bucketName, directoryPrefix, outputDirectory, includeSubDirectories);
AsperaTransaction asperaTransaction = asperaTransactionFuture.get();
int pauseCount = 0;
while (!asperaTransaction.isDone()) {
System.out.println("Directory download in progress...");
//pause the transfer
asperaTransfer.pause();
//resume the transfer
asperaTransfer.resume();
//cancel the transfer
asperaTransfer.cancel();
}
System.out.println("Directory download complete!");
疑難排解 Aspera 問題
**問題:**在 Linux 或 Mac OS X 上使用 Oracle JDK 的開發人員在傳送期間可能會遇到非預期且無聲自動的損毀
**原因:**原生程式碼需要它自己的信號處理程式,這可能會置換 JVM 的信號處理程式。 可能需要使用 JVM 的信號鏈結機能。
IBM® JDK 使用者或 Microsoft® Windows 使用者不受此影響。
**解決方案:**鏈結並載入 JVM 的信號鏈結程式庫。
-
在 Linux 上尋找
libjsig.so共用程式庫,並設定下列環境變數:LD_PRELOAD=<PATH_TO_SHARED_LIB>/libjsig.so
-
在 Mac OS X 上,尋找共用程式庫
libjsig.dylib,並設定下列環境變數:DYLD_INSERT_LIBRARIES=<PATH_TO_SHARED_LIB>/libjsig.dylibDYLD_FORCE_FLAT_NAMESPACE=0
請參閱 Oracle® JDK 文件,以取得有關訊號鏈結的更多資訊。
**問題:**Linux 上的 UnsatisfiedLinkError
**原因:**系統無法載入相依程式庫。 在應用程式日誌中,可能會看到下列錯誤:
libfaspmanager2.so: libawt.so: cannot open shared object file: No such file or directory
**解決方案:**設定下列環境變數:
LD_LIBRARY_PATH=<JAVA_HOME>/jre/lib/amd64/server:<JAVA_HOME>/jre/lib/amd64
更新 meta 資料
有兩種方式可更新現有物件上的 meta 資料:
- 具有新 meta 資料及原始物件內容的
PUT要求 - 使用新 meta 資料來執行
COPY要求,並指定原始物件作為副本來源
使用 PUT 更新 meta 資料
此 PUT 請求會覆寫物件的現有內容,因此必須先將其下載,再使用新的元資料重新上傳。
public static void updateMetadataPut(String bucketName, String itemName, String key, String value) throws IOException {
System.out.printf("Updating metadata for item: %s\n", itemName);
//retrieve the existing item to reload the contents
S3Object item = _cos.getObject(new GetObjectRequest(bucketName, itemName));
S3ObjectInputStream itemContents = item.getObjectContent();
//read the contents of the item in order to set the content length and create a copy
ByteArrayOutputStream output = new ByteArrayOutputStream();
int b;
while ((b = itemContents.read()) != -1) {
output.write(b);
}
int contentLength = output.size();
InputStream itemCopy = new ByteArrayInputStream(output.toByteArray());
//set the new metadata
HashMap<String, String> userMetadata = new HashMap<String, String>();
userMetadata.put(key, value);
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(contentLength);
metadata.setUserMetadata(userMetadata);
PutObjectRequest req = new PutObjectRequest(bucketName, itemName, itemCopy, metadata);
_cos.putObject(req);
System.out.printf("Updated metadata for item %s from bucket %s\n", itemName, bucketName);
}
使用 COPY 更新 meta 資料
public static void updateMetadataCopy(String bucketName, String itemName, String key, String value) {
System.out.printf("Updating metadata for item: %s\n", itemName);
//set the new metadata
HashMap<String, String> userMetadata = new HashMap<String, String>();
userMetadata.put(key, value);
ObjectMetadata metadata = new ObjectMetadata();
metadata.setUserMetadata(userMetadata);
//set the copy source to itself
CopyObjectRequest req = new CopyObjectRequest(bucketName, itemName, bucketName, itemName);
req.setNewObjectMetadata(metadata);
_cos.copyObject(req);
System.out.printf("Updated metadata for item %s from bucket %s\n", itemName, bucketName);
}
使用 Immutable Object Storage
將保護配置新增至現有儲存區
此 PUT 作業的實作使用 protection 查詢參數來設定現有儲存區的保留參數。 此作業可讓您設定或變更最短保留期間、預設值及最長保留期間。 此作業也可讓您變更儲存區的保護狀態。
在保護期間過期,並移除物件上的所有合法保留之前,無法刪除寫入受保護儲存區的物件。 除非在物件建立時提供物件特定值,否則會將儲存區的預設保留值提供給物件。 位於受保護儲存桶中、且已不再受保留政策約束(保留期限已屆滿,且該物件未受任何法律保留要求限制)的物件,一旦被覆寫,將再次受到保留政策的約束。 新的保留期間可作為物件覆寫請求的一部分提供,或將儲存桶的預設保留時間套用至該物件。
保留期間設定 的最小與最大支援值 MinimumRetention``DefaultRetention,分別 MaximumRetention 為至少 0 天,至多 365243 天(1000 年)。
public static void addProtectionConfigurationToBucket(String bucketName) {
System.out.printf("Adding protection to bucket: %s\n", bucketName);
BucketProtectionConfiguration newConfig = new BucketProtectionConfiguration()
.withStatus(BucketProtectionStatus.Retention)
.withMinimumRetentionInDays(10)
.withDefaultRetentionInDays(100)
.withMaximumRetentionInDays(1000);
cos.setBucketProtection(bucketName, newConfig);
System.out.printf("Protection added to bucket %s\n", bucketName);
}
public static void addProtectionConfigurationToBucketWithRequest(String bucketName) {
System.out.printf("Adding protection to bucket: %s\n", bucketName);
BucketProtectionConfiguration newConfig = new BucketProtectionConfiguration()
.withStatus(BucketProtectionStatus.Retention)
.withMinimumRetentionInDays(10)
.withDefaultRetentionInDays(100)
.withMaximumRetentionInDays(1000);
SetBucketProtectionConfigurationRequest newRequest = new SetBucketProtectionConfigurationRequest()
.withBucketName(bucketName)
.withProtectionConfiguration(newConfig);
cos.setBucketProtectionConfiguration(newRequest);
System.out.printf("Protection added to bucket %s\n", bucketName);
}
檢查儲存區的保護
public static void getProtectionConfigurationOnBucket(String bucketName) {
System.out.printf("Retrieving protection configuration from bucket: %s\n", bucketName;
BucketProtectionConfiguration config = cos.getBucketProtection(bucketName);
String status = config.getStatus();
System.out.printf("Status: %s\n", status);
if (!status.toUpperCase().equals("DISABLED")) {
System.out.printf("Minimum Retention (Days): %s\n", config.getMinimumRetentionInDays());
System.out.printf("Default Retention (Days): %s\n", config.getDefaultRetentionInDays());
System.out.printf("Maximum Retention (Days): %s\n", config.getMaximumRetentionInDays());
}
}
上傳受保護物件
位於受保護儲存桶中、且已不再受保留政策約束(保留期限已屆滿,且該物件未受任何法律保留要求限制)的物件,一旦被覆寫,將再次受到保留政策的約束。 新的保留期間可作為物件覆寫請求的一部分提供,或將儲存桶的預設保留時間套用至該物件。
| 值 | 類型 | 說明 |
|---|---|---|
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 putObjectAddLegalHold(String bucketName, String objectName, String fileText, String legalHoldId) {
System.out.printf("Add legal hold %s to %s in bucket %s with a putObject operation.\n", legalHoldId, objectName, bucketName);
InputStream newStream = new ByteArrayInputStream(fileText.getBytes(StandardCharsets.UTF_8));
ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentLength(fileText.length());
PutObjectRequest req = new PutObjectRequest(
bucketName,
objectName,
newStream,
metadata
);
req.setRetentionLegalHoldId(legalHoldId);
cos.putObject(req);
System.out.printf("Legal hold %s added to object %s in bucket %s\n", legalHoldId, objectName, bucketName);
}
public static void copyProtectedObject(String sourceBucketName, String sourceObjectName, String destinationBucketName, String newObjectName) {
System.out.printf("Copy protected object %s from bucket %s to %s/%s.\n", sourceObjectName, sourceBucketName, destinationBucketName, newObjectName);
CopyObjectRequest req = new CopyObjectRequest(
sourceBucketName,
sourceObjectName,
destinationBucketName,
newObjectName
);
req.setRetentionDirective(RetentionDirective.COPY);
cos.copyObject(req);
System.out.printf("Protected object copied from %s/%s to %s/%s\n", sourceObjectName, sourceBucketName, destinationBucketName, newObjectName);
}
新增或移除受保護物件的合法保留
物件可支援 100 個合法保留:
- 合法保留 ID 是長度上限為 64 個字元的字串,且長度下限為 1 個字元。 有效字元包括字母、數字、
!、_、.、*、(、)、-及'。 - 若新增的法律保留令使該物件的法律保留令總數超過 100 項,則不會新增該法律保留令,並會傳回一個錯誤
400。 - 若識別碼過長,則不會被新增至物件中,並會傳回一個錯誤
400。 - 若識別碼包含無效字元,則不會將其新增至物件,並會傳回一個錯誤
400。 - 如果某個 ID 已在物件上使用,則不會修改現有合法保留,且回應會指出 ID 已在使用中,並且有
409錯誤。 - 如果物件沒有保留期間 meta 資料,則會傳回
400錯誤,且不容許新增或移除合法保留。
需要有保留期間標頭,否則會傳回 400 錯誤。
正在新增或移除合法保留的使用者必須具有此儲存區的 Manager 許可權。
public static void addLegalHoldToObject(String bucketName, String objectName, String legalHoldId) {
System.out.printf("Adding legal hold %s to object %s in bucket %s\n", legalHoldId, objectName, bucketName);
cos.addLegalHold(
bucketName,
objectName,
legalHoldId
);
System.out.printf("Legal hold %s added to object %s in bucket %s!\n", legalHoldId, objectName, bucketName);
}
public static void deleteLegalHoldFromObject(String bucketName, String objectName, String legalHoldId) {
System.out.printf("Deleting legal hold %s from object %s in bucket %s\n", legalHoldId, objectName, bucketName);
cos.deleteLegalHold(
bucketName,
objectName,
legalHoldId
);
System.out.printf("Legal hold %s deleted from object %s in bucket %s!\n", legalHoldId, objectName, bucketName);
}
延長受保護物件的保留期間
只能延長物件的保留期間。 不能從目前配置的值縮短。
保留擴充值以三種方式之一來設定:
- 現行值再加上時間(
Additional-Retention-Period或類似方法) - 新擴充期間(以秒為單位)(
Extend-Retention-From-Current-Time或類似方法) - 物件的新保留到期日(
New-Retention-Expiration-Date或類似方法)
儲存在物件 meta 資料中的現行保留期間,會增加給定的額外時間,或以新值取代,視 extendRetention 要求中設定的參數而定。 在所有情況下,會針對現行保留期間檢查延長保留參數,而且只有在更新的保留期間大於現行保留期間時,才會接受延長的參數。
位於受保護儲存桶中、且已不再受保留政策約束(保留期限已屆滿,且該物件未受任何法律保留要求限制)的物件,一旦被覆寫,將再次受到保留政策的約束。 新的保留期間可作為物件覆寫請求的一部分提供,或將儲存桶的預設保留時間套用至該物件。
public static void extendRetentionPeriodOnObject(String bucketName, String objectName, Long additionalSeconds) {
System.out.printf("Extend the retention period on %s in bucket %s by %s seconds.\n", objectName, bucketName, additionalSeconds);
ExtendObjectRetentionRequest req = new ExtendObjectRetentionRequest(
bucketName,
objectName)
.withAdditionalRetentionPeriod(additionalSeconds);
cos.extendObjectRetention(req);
System.out.printf("New retention period on %s is %s\n", objectName, additionalSeconds);
}
列出受保護物件的合法保留
此作業傳回:
- 物件建立日期
- 物件保留期間(秒)
- 根據期間和建立日期計算的保留到期日
- 合法保留的清單
- 合法保留 ID
- 套用合法保留時的時間戳記
如果物件沒有任何合法保留,則會傳回空的 LegalHoldSet。 如果在物件上未指定保留期間,則會傳回 404 錯誤。
public static void listLegalHoldsOnObject(String bucketName, String objectName) {
System.out.printf("List all legal holds on object %s in bucket %s\n", objectName, bucketName);
ListLegalHoldsResult result = cos.listLegalHolds(
bucketName,
objectName
);
System.out.printf("Legal holds on bucket %s: \n", bucketName);
List<LegalHold> holds = result.getLegalHolds();
for (LegalHold hold : holds) {
System.out.printf("Legal Hold: %s", hold);
}
}
建立代管的靜態網站
這項作業需要新增 import 陳述式:
import com.ibm.cloud.objectstorage.services.s3.model.model.BucketWebsiteConfiguration;
此作業在配置時提供下列項目,且需要正確配置的用戶端:
- 字尾 (索引文件) 的儲存區配置
- 金鑰的儲存區配置 (錯誤文件)
cosClient.setBucketWebsiteConfiguration("<bucket_name>", new BucketWebsiteConfiguration("index.html", "error.html"));
後續步驟
如需相關資訊,請參閱 Javadoc。 您可以在 GitHub 儲存庫中找到專案的原始碼。