IBM Cloud Docs
Java 사용

Java 사용

IBM Cloud® Object Storage SDK for Java는 IBM Cloud Object Storage를 최대한 활용할 수 있는 기능을 제공합니다.

The 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가 작성되고 구성됩니다. 이러한 값은 인증 정보 파일 또는 환경 변수로부터 자동으로 가져올 수도 있습니다.

서비스 인증 정보를 생성하고 나면 결과 JSON 문서를 ~/.bluemix/cos_credentials에 저장할 수 있습니다. 이 SDK는 클라이언트 작성 중에 다른 인증 정보가 명시적으로 설정되지 않은 한 이 파일에서 자동으로 인증 정보를 가져옵니다. cos_credentials 파일이 HMAC 키를 포함하는 경우에는 클라이언트가 서명을 사용하여 인증하며, 그렇지 않은 경우에는 제공된 API 키를 사용하여 Bearer 토큰으로 인증합니다.

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 클래스는 기존 버킷에 있는 오브젝트를 나열하고, 새 버킷을 작성한 후 서비스 인스턴스에 있는 모든 버킷을 나열합니다.

필수 정보 수집

  • bucketNamenewBucketName고유하며 DNS를 준수하는 문자열입니다. 버킷 이름은 전체 시스템에서 고유하므로 이 예가 여러 번 실행되는 경우에는 이러한 값을 변경해야 합니다. 이름은 삭제 후에도 10 - 15분 동안 예약되어 있다는 점을 참고하십시오.
  • apiKey서비스 자격 증명에 apikey 로 표시된 값입니다.
  • serviceInstanceId서비스 자격 증명에 resource_instance_id 로 표시된 값입니다.
  • endpointUrlhttps:// 프로토콜을 포함하는 서비스 엔드포인트 URL 입니다. 이는 서비스 자격 증명에 있는 endpoints 값이 아닙니다. 엔드포인트에 대한 자세한 정보는 엔드포인트 및 스토리지 위치를 참조하십시오.
  • storageClassendpoint 값에 해당하는 유효한 프로비저닝 코드입니다. 이는 S3 API LocationConstraint 변수로 사용됩니다.
  • locationstorageClass의 위치 부분으로 설정되어야 합니다. 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>- 클라우드의 리소스 ID Object Storage ( 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);
}

오브젝트에 사용자 정의 메타데이터를 추가하는 경우에는 이 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 참조

클래스

메소드

버킷에 있는 항목 나열(v2)

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 참조

클래스

메소드

백업 정책 만들기

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);
        }

COS 버킷에 컴플라이언스 모드가 적용된 객체 잠금 구성을 설정합니다

    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);
        }

거버넌스 모드가 적용된 객체 잠금 구성을 COS 버킷에 설정

    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);
        }

COS 버킷에서 객체 잠금 구성 가져오기

    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);

        }

거버넌스 모드가 적용된 객체를 COS 버킷에 업로드합니다

    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 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);
        }

전송 관리자를 사용한 대형 오브젝트 업로드

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 검색

  1. Key Protect 서비스의 인스턴스 ID를 검색하십시오.
  2. Key Protect API를 사용하여 사용 가능한 키를 모두 검색하십시오.
    • curl 명령을 사용하거나 Postman과 같은 API REST 클라이언트를 사용하여 Key Protect API에 액세스할 수 있습니다.
  3. 버킷에서 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 서비스에서 얻은 루트 키의 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());
    }
}

ObjectListingHeadBucketResult 객체는 게터 및 세터 메서드가 있는 부울 IBMSSEKPEnabled 및 문자열 IBMSSEKPCustomerRootKeyCrn 변수를 포함하도록 업데이트되었습니다. 이들 항목이 새 헤더의 값을 저장합니다.

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 라이브러리는 클로즈드 소스이므로 COS SDK(Apache 라이센스를 사용함)의 선택적 종속 항목입니다.

각 Aspera 고속 전송 세션은 전송을 수행하기 위해 클라이언트 시스템에서 실행되는 개별 ascp 프로세스를 생성합니다. 자신의 컴퓨팅 환경이 이 프로세스의 실행을 허용하는지 확인하십시오.

AsperaTransferManager를 초기화하려면 S3 클라이언트 및 IAM 토큰 관리자 클래스의 인스턴스가 필요합니다. s3Client는 COS 대상 버킷의 FASP 연결 정보를 가져오는 데 필요합니다. tokenManager는 Aspera 고속 전송 SDK가 COS 대상 버킷에 인증할 수 있도록 하는 데 필요합니다.

AsperaTransferManager 초기화

AsperaTransferManager를 초기화하기 전에 작동하는 s3ClienttokenManager 오브젝트가 있는지 확인하십시오.

AsperaTransferManagerBuilder 를 사용하여 AsperaTransferManager 를 빌드할 때 TokenManager tokenManager = new DefaultTokenManager(new DelegateTokenProvider(apiKey)); 를 사용하고 .withTokenManager(tokenManager) 를 사용하지 않는 것이 좋습니다.

네트워크에서 심각한 잡음 또는 패킷 손실이 발생할 것으로 예상되는 경우가 아니면, Aspera 고속 전송 세션을 하나만 사용하는 것에는 큰 이점이 없습니다. 따라서 여기서는 AsperaTransferManager 클래스를 사용하여 AsperaConfig에 여러 세션을 사용하도록 지시할 것입니다. 이는 임계값 값으로 크기가 정의된 데이터 청크를 전송하는 병렬 세션의 수만큼 전송을 분할합니다.

다중 세션 사용에 대한 일반적인 구성은 다음과 같습니다.

  • 2500MBps의 목표 속도
  • 100MB의 임계값(이는 대부분의 애플리케이션에 대해 권장되는 값임)
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는 목표 속도인 2500MBps에 도달하기 위해 충분한 세션을 생성합니다.

또는 SDK에서 세션 관리를 명시적으로 구성할 수도 있습니다. 이는 네트워크 이용을 더 정확하게 제어해야 하는 경우 유용합니다.

명시적 다중 세션 사용에 대한 일반적인 구성은 다음과 같습니다.

  • 2개 또는 10개의 세션
  • 100MB의 임계값(이는 대부분의 애플리케이션에 대해 권장되는 값임)
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 고속 전송 인스턴스화와 관련된 모든 처리를 최소화하세요. 네트워크 용량이 1Gbps 이상인 경우에는 10개의 세션을 사용해야 합니다. 이보다 느린 대역폭에서는 두 개의 세션을 사용해야 합니다.

키 값

  • API_KEY - Writer 또는 Manager 역할이 있는 사용자 또는 서비스 ID의 API 키

AsperaTransferManager 를 구성하려면 IAM API 키를 제공해야 합니다. 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);
}

또한 AsperaTransaction 에서 onQueue 메소드를 호출하여 처리를 위해 전송이 큐에 대기되어 있는지 확인할 수 있습니다. 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의 progress 메소드를 호출하십시오.

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에 액세스하려면 getProgressAsperaTransaction 메소드를 사용하십시오.

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.dylib
    • DYLD_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

메타데이터 업데이트

기존 오브젝트의 메타데이터를 업데이트하는 데는 두 가지 방법이 있습니다.

  • 새 메타데이터와 원본 오브젝트 컨텐츠를 사용한 PUT 요청
  • 원본 오브젝트를 복사 소스로 지정하여, 새 메타데이터로 COPY 요청 실행

PUT을 사용한 메타데이터 업데이트

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를 사용한 메타데이터 업데이트

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);
}

불변 오브젝트 스토리지 사용

기존 버킷에 보호 구성 추가

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);
}

보호된 오브젝트의 보존 기간 연장

오브젝트의 보존 기간은 연장만 가능합니다. 현재 구성된 값에서 줄일 수는 없습니다.

보존 연장 값은 다음 세 가지 방법 중 하나로 설정됩니다.

  • 현재 값에서의 추가 시간(Additional-Retention-Period 또는 이와 유사한 메소드)
  • 초 단위의 새 연장 기간(Extend-Retention-From-Current-Time 또는 이와 유사한 메소드)
  • 오브젝트의 새 보존 만료 날짜(New-Retention-Expiration-Date 또는 이와 유사한 메소드)

오브젝트 메타데이터에 저장된 현재 보존 기간은 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 저장소에서 찾을 수 있습니다.