Usando o SDK IBM Cloud® Object Storage para Java

Fim do suporte em 6 de agosto de 2027. O SDK v1 do COS IBM Cloud® Object Storage ) atingirá o fim do suporte em 6 de agosto de 2027. Após essa data, ele não receberá mais atualizações, correções de segurança nem novas versões. Recomendamos a migração para o SDK do IBM Cloud Object Storage Java v2, que oferece melhor desempenho, segurança aprimorada, APIs modernas e suporte contínuo em IBM.

Use o SDK IBM Cloud® Object Storage para Java para criar clientes, obter credenciais, fazer upload de objetos grandes e gerenciar buckets com o Key Protect e o Aspera.

O IBM Cloud Object Storage SDK for Java é abrangente, com muitas capacidades e recursos que excedem o escopo e o espaço deste guia. Para obter a documentação detalhada de classe o método, consulte o Javadoc. O código-fonte pode ser localizado no Repositório GitHub.

Obtendo o SDK

A maneira mais fácil de usar o IBM Cloud Object Storage Java SDK é usar o Maven para gerenciar dependências. Se você não estiver familiarizado com o Maven, pode começar a usá-lo com o guia “Maven em 5 minutos ”.

O Maven usa um arquivo chamado pom.xml para especificar as bibliotecas (e suas versões) necessárias para um projeto Java. Aqui está um exemplo de arquivo pom.xml para usar o IBM Cloud Object Storage Java SDK para conexão com o Object Storage.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.cos</groupId>
    <artifactId>docs</artifactId>
    <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>

Criando um cliente e credenciais de fornecimento

No exemplo a seguir, um cliente cos é criado e configurado fornecendo informações de credenciais (Chave de API e ID da instância de serviço). Esses valores também podem ser originados automaticamente de um arquivo de credenciais ou de variáveis de ambiente.

Depois de gerar uma Credencial de serviço, o documento JSON resultante pode ser salvo em ~/.bluemix/cos_credentials. O SDK obtém automaticamente as credenciais deste arquivo, a menos que outras credenciais sejam definidas explicitamente durante a criação do cliente. Se o arquivo cos_credentials contiver chaves HMAC, o cliente será autenticado com uma assinatura, caso contrário, o cliente usará a chave de API fornecida para autenticar usando um token de acesso.

Se estiver migrando do AWS S3, também será possível originar os dados de credenciais de ~/.aws/credentials no formato:

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

Se ambos, ~/.bluemix/cos_credentials e ~/.aws/credentials, existirem, cos_credentials terá a preferência.

Para obter mais detalhes sobre a construção do cliente, consulte o Javadoc.

Exemplos de código

Em seu código, deve-se remover os colchetes ou quaisquer outros caracteres em excesso que são fornecidos aqui como ilustração.

Vamos começar com uma classe de exemplo completa que demonstra algumas funcionalidades básicas e, em seguida, explorar as classes individualmente. Essa classe CosExample lista os objetos em um bucket existente, cria um novo bucket e, em seguida, lista todos os buckets na instância do serviço.

Reunir informações necessárias

  • bucketName e newBucketName são sequências exclusivas e protegidas por DNS. Como os nomes dos depósitos são exclusivos em todo o sistema, esses valores precisarão ser mudados se este exemplo for executado múltiplas vezes. Observe que os nomes ficam reservados por 10 a 15 minutos após a exclusão.
  • apiKey é o valor encontrado na Credencial de Serviço como apikey.
  • serviceInstanceId é o valor encontrado na Credencial de Serviço como resource_instance_id.
  • endpointUrl é uma URL de ponto de extremidade do serviço, incluindo o protocolo https://. Esse não é o valor endpoints localizado na Credencial de serviço. Para obter mais informações sobre terminais, consulte Terminais e locais de armazenamento.
  • storageClass é um código de fornecimento válido que corresponde ao valor endpoint. Isso é, então, usado como a variável LocationConstraint da API S3.
  • location deve ser configurado como a parte de local do storageClass. Para us-south-standard, esse seria us-south. Essa variável é usada somente para o cálculo de assinaturas HMAC, mas é necessária para qualquer cliente, incluindo este exemplo que usa uma chave de API do IAM.
    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();
        }
    }

Inicializando a configuração

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

Valores da chave

  • <endpoint>- endpoint público para o seu Object Storage na nuvem (disponível no Painel do IBM Cloud). Para obter mais informações sobre terminais, consulte Terminais e locais de armazenamento.
  • <api-key>- chave de API gerada ao criar as credenciais do serviço (é necessário acesso de gravação para os exemplos de criação e exclusão)
  • <resource-instance-id>- ID do recurso para o seu Object Storage na nuvem (disponível por meio da CLI do IBM Cloud ou do Painel do IBM Cloud)
  • <location>- localização padrão para o seu Object Storage na nuvem (deve corresponder à região utilizada para <endpoint>)

Referências do SDK.

Classes

Determinando o terminal

Os métodos a seguir podem ser usados para determinar o terminal em serviço com base no local do depósito, tipo de terminal (público ou privado) e região específica (opcional). Para obter mais informações sobre terminais, consulte Terminais e locais de armazenamento.

/**
* 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;
}

Criando um novo depósito

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

Criar um depósito com uma classe de armazenamento diferente

Uma lista de códigos de fornecimento válidos para LocationConstraint pode ser referenciada no guia de Classes de armazenamento.

cos.createBucket("sample", "us-vault"); // the name of the bucket, and the storage class (LocationConstraint)

Referências do SDK.

Criando um novo arquivo de texto

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

Observe que ao incluir metadados customizados em um objeto, é necessário criar um objeto ObjectMetadata usando o SDK e não enviar manualmente um cabeçalho customizado contendo x-amz-meta-{key}. O último pode causar problemas ao autenticar usando credenciais HMAC.

Fazer upload do objeto de um arquivo

Este exemplo assume que o depósito sample existe.

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

Fazer upload do objeto usando um fluxo

Este exemplo assume que o depósito sample existe.

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

Como alternativa, é possível usar um CipherInputStream para criptografar mais facilmente o fluxo de dados sem precisar sobrecarregar o objeto InputStream existente.

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

Fazer download do objeto para um arquivo

Este exemplo assume que o depósito sample existe.

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

Fazer download do objeto usando um fluxo

Este exemplo assume que o depósito sample existe.

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

Copiar objetos

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

Referências do SDK.

Classes

*Métodos

putObject Exceção

O método putObject pode lançar a seguinte exceção, mesmo que o upload do novo objeto tenha sido bem-sucedido:

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

Causa raiz: as APIs JAXB são consideradas como APIs do Java EE e não estão mais contidas no caminho de classe padrão no Java SE 9.

Correção: inclua a entrada a seguir no arquivo pom.xml em sua pasta de projeto e reempacote seu projeto

<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0</version>
</dependency>

Listar depósitos disponíveis

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

Referências do SDK.

Classes

Métodos

Listar itens em um depósito (v2)

O objeto AmazonS3 contém um método atualizado para listar o conteúdo (listObjectsV2). Esse método permite limitar o número de registros que são retornados e recuperar os registros em lotes. Isso pode ser útil para paginar seus resultados em um aplicativo e melhorar o desempenho.

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

Referências do SDK.

Classes

Métodos

Obter conteúdo do arquivo de um item específico

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

Referências do SDK.

Classes

Métodos

Excluir um item de um depósito

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

Referências do SDK.

Métodos

Excluir múltiplos itens de um depósito

A solicitação de exclusão pode conter um máximo de 1000 chaves que você deseja excluir. Embora isso seja muito útil para reduzir a perda de desempenho por solicitação, tenha cuidado ao excluir um grande número de chaves. Além disso, leve em conta os tamanhos dos objetos para assegurar o desempenho adequado.

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

Referências do SDK.

Classes

Métodos

Excluir um depósito

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

Referências do SDK.

Métodos

Verificar se um objeto é legível publicamente

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

Referências do SDK.

Classes

Métodos

Executar um upload de múltiplas partes

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

Referências do SDK.

Classes

Métodos

Criação de uma política de backup

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

Listagem de uma política de backup

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

Tenha uma política de backup

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

Excluir uma política de backup

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

Criação de um cofre de backup

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

Listagem de cofres de backup

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

Obter cofres de backup

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

Atualizar cofres de backup

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

Excluir um cofre de backup

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

Faixas de recuperação de listagem

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

Obter faixa de recuperação

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

Atualizar faixa de recuperação

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

Iniciando uma restauração

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

Restauração de listagem

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

Obter detalhes da restauração

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

Crie um novo bucket COS com bloqueio de objeto ativado

    public static void createBucket(String bucketName, AmazonS3 _cosClient)
        {
            _cosClient.createBucket(bucketName);
            System.out.printf("Bucket: %s created!\n", bucketName);
        }

Configure o bloqueio de objetos com o modo de conformidade no bucket 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);
        }

Configurar o bloqueio de objetos com o modo de governança no bucket 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);
        }

Obter a configuração do bloqueio de objetos no bucket 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);
        }

Carregar um objeto com o modo de governança no bucket 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);
        }

Ative a retenção de bloqueio de objeto com o modo de conformidade no objeto

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

Ative a retenção de bloqueio de objeto com o modo de governança no objeto

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

Obter retenção de bloqueio de objeto

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

Excluindo um objeto com o modo de governança de bloqueio de objetos usando a governança de bypass

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

Fazer upload de objetos maiores usando um Transfer Manager

O TransferManager simplifica as grandes transferências de arquivos, incorporando automaticamente uploads de múltiplas partes sempre que necessário ao configurar parâmetros de configuração.

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

Referências do SDK.

Classes

Métodos

Usando o Key Protect

O Key Protect pode ser incluído em um depósito de armazenamento para criptografar dados sensíveis em repouso na nuvem.

Antes de iniciar

Os itens a seguir são necessários para criar um bucket com o Key-Protect ativado:

Recuperando o CRN da chave raiz

  1. Recupere o ID da instância para seu serviço Key Protect
  2. Use a API do Key Protect para recuperar todas as suas chaves disponíveis
  3. Recupere o CRN da chave raiz que você usa para habilitar o Key Protect no seu bucket. O CRN se parece com o exemplo a seguir:

crn:v1:bluemix:public:kms:us-south:a/3d624cd74a0dea86ed8efe3101341742:90b6a1db-0fe1-4fe9-b91e-962c327df531:key:0bg3e33e-a866-50f2-b715-5cba2bc93234

Criando um depósito com o Key-Protect ativado

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

Valores da chave

  • <algorithm>- O algoritmo de criptografia utilizado para novos objetos adicionados ao bucket (o padrão é o AES256 ).
  • <root-key-crn>- CRN da chave raiz obtida do serviço Key Protect.

Referências do SDK.

Classes

Métodos

Novos cabeçalhos para o Key Protect

Os cabeçalhos adicionais foram definidos na classe 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";

A mesma seção da implementação de criação de bucket que já adiciona cabeçalhos de instância de serviço do IAM também adiciona os dois novos cabeçalhos de criptografia:

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

Os HeadBucketResult objetos ObjectListing e foram atualizados para incluir IBMSSEKPCustomerRootKeyCrn variáveis booleanas e IBMSSEKPEnabled String com métodos getter e setter. Eles armazenam os valores dos novos cabeçalhos.

GET depósito

public ObjectListing listObjects(String bucketName)
public ObjectListing listObjects(String bucketName, String prefix)
public ObjectListing listObjects(ListObjectsRequest listObjectsRequest)

A classe ObjectListing requer 2 métodos adicionais:

ObjectListing listing = s3client.listObjects(listObjectsRequest)
String KPEnabled = listing.getIBMSSEKPEnabled();
String crkId = listing.getIBMSSEKPCrkId();

Os cabeçalhos adicionais foram definidos dentro da classe 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";

O S3XmlResponseHandler que é responsável por desserializar todas as respostas xml. Foi adicionada uma verificação para garantir que o resultado seja uma instância de ObjectListing e que os cabeçalhos recuperados sejam adicionados ao objeto 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 depósito

Os cabeçalhos adicionais foram definidos na classe 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";

Estas variáveis são preenchidas no 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();

Usando o Aspera High-Speed Transfer

Ao instalar a biblioteca de transferência de alta velocidade da Aspera, você poderá realizar transferências de arquivos em alta velocidade dentro do seu aplicativo. A biblioteca Aspera é de código fechado e, portanto, uma dependência opcional para o SDK Object Storage (que utiliza uma licença Apache ).

Cada sessão do Aspera high-speed transfer gera um processo ascp individual que é executado na máquina do cliente para executar a transferência. Assegure-se de que seu ambiente de computação possa permitir que esse processo seja executado.

Você precisa de instâncias das classes Cliente S3 e Gerenciador de tokens do IAM para inicializar o AsperaTransferManager. O s3Client é necessário para obter as informações de conexão do FASP para o bucket de destino Object Storage. O tokenManager é necessário para permitir que o SDK de transferência em alta velocidade da Aspera se autentique no bucket de destino Object Storage.

Inicializando o AsperaTransferManager

Antes de inicializar o AsperaTransferManager, certifique-se de que você tenha trabalhado com objetos s3Client e tokenManager.

É recomendável usar TokenManager tokenManager = new DefaultTokenManager(new DelegateTokenProvider(apiKey)); e evitar .withTokenManager(tokenManager) ao construir AsperaTransferManager com AsperaTransferManagerBuilder.

Não há muito benefício em usar uma única sessão do Aspera high-speed transfer, a menos que você espere ver um ruído significativo ou perda de pacote na rede. Portanto, é necessário informar ao AsperaTransferManager para usar múltiplas sessões usando a classe AsperaConfig. Isso divide a transferência em várias sessões paralelas que enviam blocos de dados cujo tamanho é definido pelo valor limite.

A configuração típica para usar múltiplas sessões deve ser:

  • Taxa de destino de 2500 MBps
  • Limite de 100 MB (esse é o valor recomendado para a maioria dos aplicativos)
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();

No exemplo acima, o sdk gera sessões suficientes para tentar atingir a taxa de destino de 2500 MBps.

Como alternativa, o gerenciamento de sessões pode ser configurado explicitamente no sdk. Isso é útil em casos em que o controle mais preciso sobre a utilização de rede é desejado.

A configuração típica para usar múltiplas sessões explícitas deve ser:

  • 2 ou 10 sessões
  • Limite de 100 MB (esse é o valor recomendado para a maioria dos aplicativos)
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();

Para obter o melhor desempenho na maioria dos cenários, utilize sempre várias sessões para minimizar qualquer processamento associado à instância de uma transferência de alta velocidade da Aspera. Se sua capacidade de rede for pelo menos 1 Gbps, será necessário usar 10 sessões. As redes de largura da banda inferior devem usar duas sessões.

Valores da chave

  • API_KEY - uma chave de API para um ID de usuário ou de serviço com funções de Gravador ou Gerenciador

É necessário fornecer uma chave de API do IAM para criar um AsperaTransferManager. Credenciais de HMAC NÃO são suportadas atualmente Para obter mais informações sobre o IAM, clique aqui.

Upload de arquivo

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

Valores da chave

  • <bucket-name>- nome do bucket na sua instância do serviço Object Storage que tem o Aspera habilitado.
  • <absolute-path-to-source-data>- nome do diretório e do arquivo a ser enviado para o Object Storage.
  • <item-name>- nome do novo objeto adicionado ao bucket.

Download de arquivo

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

Valores da chave

  • <bucket-name>- nome do bucket na sua instância do serviço Object Storage que tem o Aspera habilitado.
  • <absolute-path-to-file>- nome do diretório e do arquivo a ser salvo no Object Storage.
  • <item-name>- nome do objeto no bucket.

Upload de diretório

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

Valores da chave

  • <bucket-name>- nome do bucket na sua instância do serviço Object Storage que tem o Aspera habilitado.
  • <absolute-path-to-directory>- diretório dos arquivos a serem enviados para o Object Storage.
  • <virtual-directory-prefix>- nome do prefixo do diretório a ser adicionado a cada arquivo no momento do upload. Use a sequência nula ou vazia para fazer upload dos arquivos para a raiz do depósito.

Download de diretório

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

Valores da chave

  • <bucket-name>- nome do bucket na sua instância do serviço Object Storage que tem o Aspera habilitado.
  • <absolute-path-to-directory>- diretório para salvar arquivos baixados do Object Storage.
  • <virtual-directory-prefix>- nome do prefixo do diretório de cada arquivo a ser baixado. Use uma sequência nula ou vazia para fazer download de todos os arquivos no depósito.

Substituindo a configuração de sessão em uma Base por transferência

É possível substituir os valores de configuração de múltiplas sessões em uma base por transferência passando uma instância de AsperaConfig para os métodos de upload e download sobrecarregados. Usando AsperaConfig, é possível especificar o número de sessões e o tamanho mínimo do limite de arquivo por sessão.

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

Monitorando o progresso de transferência

A maneira mais simples de monitorar o progresso de suas transferências de arquivo/diretório é usar a propriedade isDone() que retorna true quando sua transferência é concluída.

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

Você também pode verificar se uma transferência está na fila para processamento chamando o método onQueue no AsperaTransaction. onQueue retorna um valor booleano, em que true indica que a transferência está na fila.

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

Para verificar se uma transferência está em andamento, chame o método de progresso em 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);
}

Por padrão, toda transferência tem um anexado TransferProgress a ela. O relata TransferProgress o número de bytes transferidos e a porcentagem transferida do total de bytes a serem transferidos. Para acessar o TransferProgress de uma transferência, use o método getProgress em 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);
}

Para relatar o número de bytes transferidos, chame o método getBytesTransferred em TransferProgress. Para relatar a porcentagem transferida do total de bytes a serem transferidos, chame o método getPercentTransferred em 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);
}

Pausar/Continuar/Cancelar

O SDK fornece a capacidade de gerenciar o progresso de transferências de arquivos/diretórios por meio dos métodos a seguir do objeto AsperaTransfer:

  • pause()
  • resume()
  • cancel()

Não há efeitos colaterais ao chamar um dos métodos descritos acima. A limpeza e a manutenção adequadas são manipuladas pelo SDK.

O exemplo a seguir mostra um possível uso para esses métodos:

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

Resolução de problemas do Aspera

Problema: os desenvolvedores que usam o Oracle JDK no Linux ou Mac OS X podem sofrer travamentos inesperados e silenciosos durante as transferências

Causa: o código nativo requer seus próprios manipuladores de sinal que podem estar substituindo os manipuladores de sinal da JVM. Pode ser necessário usar o recurso de encadeamento de sinal da JVM.

Os usuários do IBM® JDK ou do Microsoft® Windows não são afetados.

Solução: vincule e carregue a biblioteca de encadeamento de sinal da JVM.

  • No Linux, localize a biblioteca compartilhada libjsig.so e configure a variável de ambiente a seguir:

    • LD_PRELOAD=<PATH_TO_SHARED_LIB>/libjsig.so
  • No Mac OS X, localize a biblioteca compartilhada libjsig.dylib e configure as variáveis de ambiente a seguir:

    • DYLD_INSERT_LIBRARIES=<PATH_TO_SHARED_LIB>/libjsig.dylib
    • DYLD_FORCE_FLAT_NAMESPACE=0

Acesse a documentação do JDK da Oracle® para obter mais informações sobre encadeamento de sinais.

Problema: UnsatisfiedLinkError no Linux

Causa: o sistema não é capaz de carregar bibliotecas dependentes. Erros como os a seguir podem ser vistos nos logs do aplicativo:

libfaspmanager2.so: libawt.so: cannot open shared object file: No such file or directory

Solução: configure a variável de ambiente a seguir:

LD_LIBRARY_PATH=<JAVA_HOME>/jre/lib/amd64/server:<JAVA_HOME>/jre/lib/amd64

Atualizando os metadados

Há duas maneiras de atualizar os metadados em um objeto existente:

  • Uma solicitação PUT com os novos metadados e o conteúdo do objeto original
  • Executando uma solicitação COPY com os novos metadados especificando o objeto original como a origem de cópia

Usando PUT para atualizar metadados

A solicitação PUT sobrescreve o conteúdo existente do objeto; portanto, ele deve primeiro ser baixado e reenviado com os novos metadados.

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

Usando COPY para atualizar metadados

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

Usando o Immutable Object Storage

Incluir uma configuração de proteção em um depósito existente

Essa implementação da operação PUT usa o parâmetro de consulta protection para configurar os parâmetros de retenção para um depósito existente. Essa operação permite configurar ou mudar os períodos mínimo, padrão e máximo de retenção. Essa operação também permite mudar o estado de proteção do depósito.

Os objetos gravados em um depósito protegido não podem ser excluídos até que o período de proteção tenha expirado e todas as retenções legais no objeto sejam removidas. O valor de retenção padrão do depósito é fornecido para um objeto, a menos que um valor específico do objeto seja fornecido quando o objeto for criado. Os objetos em buckets protegidos que não estão mais sob retenção (o período de retenção expirou e o objeto não está sujeito a nenhuma retenção legal), quando sobrescritos, voltam a ficar sob retenção. O novo período de retenção pode ser fornecido como parte da solicitação de sobrescrita do objeto, ou o tempo de retenção padrão do bucket é aplicado ao objeto.

Os valores mínimo e máximo suportados para as configurações do período de retenção MinimumRetention, DefaultRetention, e MaximumRetention são, no mínimo, 0 dias e, no máximo, 365.243 dias (1.000 anos).

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

Verificar a proteção em um depósito

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

Fazer upload de um objeto protegido

Os objetos em buckets protegidos que não estão mais sob retenção (o período de retenção expirou e o objeto não está sujeito a nenhuma retenção legal), quando sobrescritos, voltam a ficar sob retenção. O novo período de retenção pode ser fornecido como parte da solicitação de sobrescrita do objeto, ou o tempo de retenção padrão do bucket é aplicado ao objeto.

Valor Tipo Descrição
Retention-Period Número inteiro não negativo (segundos) O período de retenção para armazenar o objeto em segundos. O objeto não pode ser sobrescrito nem excluído até que a quantia de tempo especificada no período de retenção tenha decorrido. Se esse campo e Retention-Expiration-Date forem especificados, um erro 400 será retornado. Se nenhuma das opções for especificada, será utilizado o período DefaultRetention do bucket. Zero (0) é um valor legal que supõe que o período mínimo de retenção do depósito também é 0.
Retention-expiration-date Data (formato ISO 8601) A data em que é legal excluir ou modificar o objeto. É possível especificar somente isso ou o cabeçalho Retention-Period. Se ambos forem especificados, é retornado um erro 400. Se nenhuma das opções for especificada, será utilizado o período de retenção padrão ( DefaultRetention ) do bucket.
Retention-legal-hold-id string Uma única retenção legal para aplicar ao objeto. Uma retenção legal é uma sequência longa de caracteres Y. O objeto não pode ser sobrescrito nem excluído até que todas as retenções legais associadas ao objeto sejam removidas.
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);
}

Ampliar o período de retenção de um objeto protegido

O período de retenção de um objeto pode somente ser ampliado. Ele não pode ser diminuído do valor configurado atualmente.

O valor de expansão de retenção é configurado de uma de três maneiras:

  • tempo adicional do valor atual (Additional-Retention-Period ou método semelhante)
  • novo período de extensão em segundos (Extend-Retention-From-Current-Time ou método semelhante)
  • nova data de validade de retenção do objeto (New-Retention-Expiration-Date ou método semelhante)

O período de retenção atual armazenado nos metadados do objeto é aumentado pelo tempo adicional fornecido ou substituído pelo novo valor, dependendo do parâmetro que está configurado na solicitação extendRetention. Em todos os casos, o parâmetro de ampliação de retenção é verificado com relação ao período de retenção atual e o parâmetro ampliado será aceito somente se o período de retenção atualizado for maior que o período de retenção atual.

Os objetos em buckets protegidos que não estão mais sob retenção (o período de retenção expirou e o objeto não está sujeito a nenhuma retenção legal), quando sobrescritos, voltam a ficar sob retenção. O novo período de retenção pode ser fornecido como parte da solicitação de sobrescrita do objeto, ou o tempo de retenção padrão do bucket é aplicado ao objeto.

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

Listar retenções legais em um objeto protegido

Essa operação retorna:

  • Data de criação do objeto
  • Período de retenção do objeto em segundos
  • Data de expiração de retenção calculada com base no período e data de criação
  • Lista de retenções legais
  • Identificador de retenção legal
  • Registro de data e hora em que a retenção legal foi aplicada

Se não houver retenções legais no objeto, um LegalHoldSet vazio será retornado. Se não houver nenhum período de retenção especificado no objeto, um erro 404 será retornado.

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

Criar um website estático hospedado

Esta operação requer que uma instrução de importação seja incluída:

import com.ibm.cloud.objectstorage.services.s3.model.model.BucketWebsiteConfiguration;

Esta operação fornece o seguinte na configuração e requer um cliente configurado corretamente:

  • Configuração do depósito para sufixo (documento de índice)
  • Configuração do depósito para chave (documento de erro)
cosClient.setBucketWebsiteConfiguration("<bucket_name>", new BucketWebsiteConfiguration("index.html", "error.html"));

Próximas etapas

Para obter mais informações, consulte o Javadoc O código-fonte para o projeto pode ser localizado no GitHub repositório.