Upload auf S3 mit der jclouds-Bibliothek

Es gibt mehrere Möglichkeiten, Inhalte in einen S3-Bucket in der Java-Welt hochzuladen. In diesem Artikel wird beschrieben, was für diesen Zweck the jclouds library zur Verfügung steht.

Um Jclouds zu verwenden, insbesondere die in diesem Artikel beschriebenen APIs, verwenden Sie die folgenden Anweisungen: allblobstore% 22[simple Maven Abhängigkeit]sollte zum Pom des Projekts hinzugefügt werden:

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

1. Hochladen auf Amazon S3

Um auf eine dieser APIs zuzugreifen, müssen Sie zunächst einen BlobStoreContext erstellen:

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

Dies ist der Einstiegspunkt in einen allgemeinen Schlüsselwertspeicherdienst wie Amazon S3 - jedoch nicht darauf beschränkt.

Für die spezifischere S3-only-Implementierung kann der Kontext auf ähnliche Weise erstellt werden:

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

Und noch genauer:

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

Wenn der authentifizierte Kontext nicht mehr benötigt wird, müssen Schliessen alle damit verbundenen Ressourcen (Threads und Verbindungen) freigegeben werden.

2. Die vier S3-APIs von Jclouds

Die jclouds-Bibliothek bietet vier verschiedene APIs zum Hochladen von Inhalten in den S3-Bucket, von einfach, aber unflexibel bis hin zu komplex und leistungsstark, die über den BlobStoreContext abgerufen werden. Beginnen wir mit dem einfachsten.

2.1. Hochladen über die Map API

Die einfachste Möglichkeit, mit Jclouds mit einem S3-Bucket zu interagieren, besteht darin, diesen Bucket als Map darzustellen. Die API wird aus dem Kontext abgerufen:

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

Dann laden Sie eine einfache HTML-Datei hoch:

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

Die InputStreamMap -API macht mehrere andere Arten von PUT-Operationen verfügbar - Dateien und unformatierte Bytes - sowohl für Einzel- als auch für Massenbündel.

Ein einfacher Integrationstest kann als Beispiel dienen:

@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. Hochladen via BlobMap

Die Verwendung der einfachen Map-API ist unkompliziert, aber letztendlich beschränkt. Zum Beispiel gibt es keine Möglichkeit, Metadaten über den hochgeladenen Inhalt zu übergeben. Wenn mehr Flexibilität und Anpassungen erforderlich sind, reicht dieser vereinfachte Ansatz zum Hochladen von Daten über eine Karte nach S3 nicht mehr aus.

Die nächste API, die wir uns ansehen werden, ist die Blob-Map-API. Diese wird aus dem Kontext abgerufen:

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

Über die API kann der Client auf weitere Details auf unterer Ebene zugreifen, z. um neue Inhalte in den Bucket hochzuladen:

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

Die API ermöglicht auch das Festlegen verschiedener Nutzdaten für die Erstellanforderung.

Ein einfacher Integrationstest zum Hochladen einer einfachen HTML-Datei in S3 über die Blob-Map-API:

@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. Hochladen über BlobStore

Die vorherigen APIs hatten keine Möglichkeit, Inhalte mit multipart upload hochzuladen. Dies macht sie für die Arbeit mit großen Dateien ungeeignet. Diese Einschränkung wird durch die nächste API behoben, die wir uns anschauen werden - die synchrone BlobStore-API.

Dies ergibt sich aus dem Kontext:

BlobStore blobStore = context.getBlobStore();

So verwenden Sie die Multipart-Unterstützung und laden eine Datei in S3 hoch:

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

Der Payload-Builder ist derselbe, der von der BlobMap -API verwendet wurde. Daher ist hier dieselbe Flexibilität bei der Angabe von Metadateninformationen auf niedriger Ebene für das Blob verfügbar. Der Unterschied ist der PutOptions , der von der PUT-Operation der API unterstützt wird - nämlich die Multipart-Unterstützung .

Der vorherige Integrationstest hat jetzt Multipart aktiviert:

@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. Hochladen über AsyncBlobStore

Während die vorherige BlobStore-API synchron war, gibt es auch eine asynchrone API für BlobStore - AsyncBlobStore . Die API wird auf ähnliche Weise aus dem Kontext abgerufen:

AsyncBlobStore blobStore = context.getAsyncBlobStore();

Der einzige Unterschied zwischen den beiden besteht darin, dass die asynchrone API ListenableFuture für die asynchrone PUT -Operation zurückgibt:

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

Der Integrationstest, der diesen Vorgang anzeigt, ist dem synchronen ähnlich:

@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. Fazit

In diesem Artikel haben wir die vier APIs analysiert, die die jclouds-Bibliothek zum Hochladen von Inhalten zu Amazon S3 bereitstellt. Diese vier APIs sind generisch und funktionieren auch mit anderen Schlüsseldatenspeicherdiensten - beispielsweise Microsoft Azure Storage.

Im nächsten Artikel werden wir uns die Amazon-spezifische S3-API ansehen, die in jclouds verfügbar ist - den AWSS3Client . Wir implementieren das Hochladen einer großen Datei, berechnen dynamisch die optimale Anzahl von Teilen für eine bestimmte Datei und führen das Hochladen aller Teile parallel aus.