Javaの世界でコンテンツをS3バケットにアップロードするには、いくつかの良い方法があります。この記事では、jcloudsライブラリがこの目的のために提供するものを見ていきます。

jclouds –特にこの記事で説明されているAPIを使用するには、この単純なMaven依存関係をプロジェクトのpomに追加する必要があります。

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

1. AmazonS3へのアップロード

これらのAPIのいずれかにアクセスするための最初のステップは、BlobStoreContextを作成することです。

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

これは、Amazon S3などの一般的なKey-Valueストレージサービスへのエントリポイントを表しますが、これに限定されません。

より具体的なS3のみの実装の場合、コンテキストは同様に作成できます。

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

そしてさらに具体的に:

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

認証されたコンテキストが不要になったら、を閉じる、それに関連付けられているすべてのリソース(スレッドと接続)を解放する必要があります。

2. jcloudsの4つのS3API

jcloudsライブラリは、コンテンツをS3バケットにアップロードするための4つの異なるAPIを提供します。これらは、単純だが柔軟性がないものから複雑で強力なものまで、すべてBlobStoreContextを介して取得されます。 最も単純なものから始めましょう。

2.1. MapAPIを介してアップロード

jcloudsを使用してS3バケットを操作する最も簡単な方法は、そのバケットをマップとして表すことです。 APIはコンテキストから取得されます。

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

次に、単純なHTMLファイルをアップロードするには:

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

InputStreamMap APIは、他のいくつかのタイプのPUT操作(ファイル、rawバイト)をシングルとバルクの両方で公開します。

簡単な統合テストを例として使用できます。

@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. BlobMap経由でアップロード

単純なMapAPIの使用は簡単ですが、最終的には制限されます。たとえば、アップロードされるコンテンツに関するメタデータを渡す方法はありません。 より柔軟性とカスタマイズが必要な場合、マップを介してS3にデータをアップロードするためのこの単純化されたアプローチではもはや十分ではありません。

次に説明するAPIはBlobMapAPIです。これは、コンテキストから取得されます。

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

APIを使用すると、クライアントは Content Length Content-Type Content-Encoding eTagハッシュなど。 バケットに新しいコンテンツをアップロードするには:

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

APIでは、作成リクエストでさまざまなペイロードを設定することもできます。

Blob MapAPIを介して基本的なHTMLファイルをS3にアップロードするための簡単な統合テスト:

@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. BlobStore経由でアップロード

以前のAPIには、マルチパートアップロードを使用してコンテンツをアップロードする方法がありませんでした。これにより、大きなファイルを操作する場合に不適切になります。 この制限は、これから説明する次のAPIである同期BlobStoreAPIによって対処されます。

これはコンテキストから取得されます。

BlobStore blobStore = context.getBlobStore();

マルチパートサポートを使用してファイルを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());

ペイロードビルダーは、 BlobMap APIで使用されていたものと同じであるため、blobに関する下位レベルのメタデータ情報を指定する際の同じ柔軟性がここで利用できます。 違いは、APIのPUT操作でサポートされる PutOptions 、つまりマルチパートサポートです。

以前の統合テストでは、マルチパートが有効になりました。

@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. AsyncBlobStore経由でアップロード

以前のBlobStoreAPIは同期でしたが、 BlobStore AsyncBlobStore用の非同期APIもあります。 APIも同様に、コンテキストから取得されます。

AsyncBlobStore blobStore = context.getAsyncBlobStore();

2つの違いは、非同期APIがPUT非同期操作に対してListenableFutureを返すことだけです。

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

この操作を表示する統合テストは、同期テストと似ています。

@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. 結論

この記事では、jcloudsライブラリがAmazonS3にコンテンツをアップロードするために提供する4つのAPIを分析しました。 これらの4つのAPIはgenericであり、MicrosoftAzureStorageなどの他のKey-Valueストレージサービスでも機能します。

次の記事では、jcloudsで利用可能なAmazon固有のS3 API – AWSS3Clientについて説明します。 大きなファイルをアップロードする操作を実装し、任意のファイルの最適なパーツ数を動的に計算し、すべてのパーツのアップロードを並行して実行します。