Télécharger sur S3 avec la bibliothèque jclouds

Dans le monde Java, il existe plusieurs moyens de télécharger du contenu vers un compartiment S3. Dans cet article, nous allons examiner ce que the jclouds fournit à cette fin.

Pour utiliser jclouds, en particulier les API décrites dans cet article, consultez la page https://search.maven.org/classic/#search%7Cgav%7C1%7Cg%3A%22org.jclouds%22%20and%20a%3A%22jclouds- allblobstore% 22[dépendance Maven simple]doit être ajouté au pom du projet:

<dependency>
   <groupId>org.jclouds</groupId>
   <artifactId>jclouds-allblobstore</artifactId>
   <version>1.5.10</version>
</dependency>

1. Téléchargement sur Amazon S3

La première étape, pour accéder à l’une de ces API, consiste à créer un BlobStoreContext :

BlobStoreContext context =
  ContextBuilder.newBuilder("aws-s3").credentials(identity, credentials)
    .buildView(BlobStoreContext.class);

Cela représente le point d’entrée d’un service de stockage clé-valeur général, tel qu’Amazon S3, sans toutefois s’y limiter.

Pour l’implémentation S3 uniquement plus spécifique, le contexte peut être créé de la même manière:

BlobStoreContext context =
  ContextBuilder.newBuilder("aws-s3").credentials(identity, credentials)
    .buildView(S3BlobStoreContext.class);

Et encore plus spécifiquement:

BlobStoreContext context =
  ContextBuilder.newBuilder("aws-s3").credentials(identity, credentials)
    .buildView(AWSS3BlobStoreContext.class);

Lorsque le contexte authentifié n’est plus nécessaire, close doit libérer toutes les ressources - threads et connexions - qui lui sont associées.

2. Les quatre API S3 de jclouds

La bibliothèque jclouds fournit quatre API différentes pour télécharger du contenu vers un compartiment S3, allant du simple mais inflexible au complexe et puissant, le tout obtenu via le BlobStoreContext . Commençons par le plus simple.

2.1. Télécharger via l’API Map

La manière la plus simple d’utiliser jclouds pour interagir avec un compartiment S3 consiste à représenter ce dernier en tant que carte. L’API est obtenue à partir du contexte:

InputStreamMap bucket = context.createInputStreamMap("bucketName");

Ensuite, pour télécharger un simple fichier HTML:

bucket.putString("index1.html", "<html><body>hello world1</body></html>");

L’API InputStreamMap expose plusieurs autres types d’opérations PUT - fichiers, octets bruts - à la fois pour les opérations simples et en masse.

Un test d’intégration simple peut être utilisé à titre d’exemple:

@Test
public void whenFileIsUploadedToS3WithMapApi__thenNoExceptions() {
   BlobStoreContext context =
      ContextBuilder.newBuilder("aws-s3").credentials(identity, credentials)
         .buildView(AWSS3BlobStoreContext.class);

   InputStreamMap bucket = context.createInputStreamMap("bucketName");

   bucket.putString("index1.html", "<html><body>hello world1</body></html>");
   context.close();
}

2.2. Télécharger via BlobMap

L’utilisation de la simple API de carte est simple mais finalement limitée. Par exemple, il est impossible de transmettre des métadonnées sur le contenu téléchargé. Lorsque plus de flexibilité et de personnalisation sont nécessaires, cette approche simplifiée du téléchargement de données vers S3 via une carte ne suffit plus.

La prochaine API que nous examinerons est l’API Blob Map - elle est obtenue à partir du contexte:

BlobMap bucket = context.createBlobMap("bucketName");

L’API permet au client d’accéder à plus de détails de niveau inférieur, tels que Content Length , Content-Type , Content-Encoding , eTag hash et autres; pour télécharger un nouveau contenu dans le compartiment:

Blob blob = bucket.blobBuilder().name("index2.html").
   payload("<html><body>hello world2</body></html>").
      contentType("text/html").calculateMD5().build();

L’API permet également de définir diverses charges utiles sur la demande de création.

Un test d’intégration simple pour télécharger un fichier HTML de base sur S3 via l’API Blob Map:

@Test
public void whenFileIsUploadedToS3WithBlobMap__thenNoExceptions() throws IOException {
   BlobStoreContext context =
      ContextBuilder.newBuilder("aws-s3").credentials(identity, credentials)
         .buildView(AWSS3BlobStoreContext.class);

   BlobMap bucket = context.createBlobMap("bucketName");

   Blob blob = bucket.blobBuilder().name("index2.html").
      payload("<html><body>hello world2</body></html>").
         contentType("text/html").calculateMD5().build();
   bucket.put(blob.getMetadata().getName(), blob);

   context.close();
}

2.3. Transférer via BlobStore

Les API précédentes ne permettaient pas de télécharger du contenu en utilisant upload multipart - cela les rendait mal adaptées au travail avec des fichiers volumineux. Cette limitation est résolue par la prochaine API que nous allons examiner - l’API synchrone BlobStore.

Ceci est obtenu à partir du contexte:

BlobStore blobStore = context.getBlobStore();

Pour utiliser le support multipart et télécharger un fichier sur S3:

Blob blob = blobStore.blobBuilder("index3.html").
   payload("<html><body>hello world3</body></html>").contentType("text/html").build();
blobStore.putBlob("bucketName", blob, PutOptions.Builder.multipart());

Le générateur de données utiles est le même que celui utilisé par l’API BlobMap . Vous disposez donc ici de la même souplesse pour spécifier des informations de métadonnées de niveau inférieur sur l’objet blob. La différence réside dans le PutOptions pris en charge par l’opération PUT de l’API, à savoir le support multipart .

Le test d’intégration précédent a maintenant activé la multi-partie:

@Test
public void whenFileIsUploadedToS3WithBlobStore__thenNoExceptions() {
   BlobStoreContext context =
      ContextBuilder.newBuilder("aws-s3").credentials(identity, credentials)
         .buildView(AWSS3BlobStoreContext.class);

   BlobStore blobStore = context.getBlobStore();

   Blob blob = blobStore.blobBuilder("index3.html").
      payload("<html><body>hello world3</body></html>").contentType("text/html").build();
   blobStore.putBlob("bucketName", blob, PutOptions.Builder.multipart());
   context.close();
}

2.4. Transférer via AsyncBlobStore

Alors que l’ancienne API BlobStore était synchrone, il existe également une API asynchrone pour BlobStore - AsyncBlobStore . De même, l’API est obtenue à partir du contexte:

AsyncBlobStore blobStore = context.getAsyncBlobStore();

La seule différence entre les deux réside dans le fait que l’API asynchrone renvoie ListenableFuture pour l’opération asynchrone PUT :

Blob blob = blobStore.blobBuilder("index4.html").
   .payload("<html><body>hello world4</body></html>").build();
blobStore.putBlob("bucketName", blob)<strong>.get()</strong>;

Le test d’intégration affichant cette opération est similaire à celui synchrone:

@Test
public void whenFileIsUploadedToS3WithBlobStore__thenNoExceptions() {
   BlobStoreContext context =
      ContextBuilder.newBuilder("aws-s3").credentials(identity, credentials)
         .buildView(AWSS3BlobStoreContext.class);

   BlobStore blobStore = context.getBlobStore();

   Blob blob = blobStore.blobBuilder("index4.html").
      payload("<html><body>hello world4</body></html>").contentType("text/html").build();
   Future<String> putOp = blobStore.putBlob("bucketName", blob, PutOptions.Builder.multipart());
   putOp.get();
   context.close();
}

3. Conclusion

Dans cet article, nous avons analysé les quatre API fournies par la bibliothèque jclouds pour le téléchargement de contenu vers Amazon S3. Ces quatre API sont génériques et fonctionnent également avec d’autres services de stockage clé-valeur, tels que Microsoft Azure Storage, par exemple.

Dans le prochain article, nous examinerons l’API S3 spécifique à Amazon disponible dans jclouds - le AWSS3Client . Nous allons mettre en œuvre le téléchargement d’un fichier volumineux, calculer dynamiquement le nombre optimal de pièces pour un fichier donné et effectuer le téléchargement de toutes les pièces en parallèle.