課題
AWS SDK for Javaで、S3オブジェクトの一覧を取得する機能を利用するとき、日本語でまとまった情報を入手するのに苦労しました。
解決方針
どのようにSDKを利用したか、この記事にまとめます。
方法
前提
- Javaバージョン: 17
- AWS SDKバージョン: v2
共通の注意点
- 1回のリクエストで、すべてのオブジェクトが取得されるとは限りません。
- 取得したオブジェクト一覧を格納したクラスには、以下の情報が含まれます。
- a. 取得しきれなかったオブジェクトがあるか否か
- b. 取得したオブジェクト一覧末尾の、次のオブジェクトを示すトークン
- 取得しきれなかったオブジェクトを取得する際に、このトークンが示す位置から取得を開始します。
- 取得したオブジェクト一覧を格納したクラスには、以下の情報が含まれます。
バージョニングが無効のとき
software.amazon.awssdk.services.s3.model.ListObjectsV2Request
クラスを利用します。
一例として、以下のgetAllS3Contents
メソッドでは、バケット内にあるすべてのオブジェクトを、リストに格納して返却しています。
// S3クライアントを用意
private final S3Client s3Client;
// 初回に呼び出すメソッド
public List<S3Object> getAllS3Contents(String bucketName) {
return getAllS3Contents(bucketName, new ArrayList<S3Object>(), null);
}
// 再帰的に呼び出すメソッド
private List<S3Object> getAllS3Contents(String bucketName, List<S3Object> objects, String continuationToken) {
// リクエスト作成
var listReq = ListObjectsV2Request.builder()
.bucket(bucketName)
.continuationToken(continuationToken)
.build();
// レスポンス取得
var res = s3Client.listObjectsV2(listReq);
// S3オブジェクトリスト取得
var currentObjects = res.contents();
// 前のステップで取得したS3オブジェクトリストを連結
objects.addAll(currentObjects);
// 次のステップで取得を開始する位置
var nextContinuationToken = res.nextContinuationToken(); // (b, aが`false`の場合は`null`)
// 一度にすべてのS3オブジェクトを取得しきれなかった場合、S3オブジェクトリストと開始位置を更新して、このメソッドを再帰的に呼び出す
if (res.isTruncated()) { // (a)
return getAllS3Contents(bucketName, objects, nextContinuationToken);
}
return objects;
}
バージョニングが有効のとき
software.amazon.awssdk.services.s3.model.ListObjectVersionsRequest
クラスを利用します。
一例として、以下のgetAllS3Versions
メソッドでは、バケット内にあるすべてのオブジェクトバージョンを、リストに格納して返却しています。
以下の点以外は、バージョニングが無効のときと同じです。
- 返り値の型を
ObjectVersion
に変更。 - 次のオブジェクトを示すトークン(b)に、バージョンを示す情報を追加。
// S3クライアントを用意
private final S3Client s3Client;
// 初回に呼び出すメソッド
public List<ObjectVersion> getAllS3Versions(String bucketName) {
return getAllS3Versions(bucketName, new ArrayList<ObjectVersion>(), null, null);
}
// 再帰的に呼び出すメソッド
private List<ObjectVersion> getAllS3Versions(String bucketName, List<ObjectVersion> objVerList, String keyMarker, String versionIdMarker) {
// リクエスト作成
var listReq = ListObjectVersionsRequest.builder()
.bucket(bucketName)
.keyMarker(keyMarker)
.versionIdMarker(versionIdMarker)
.build();
// レスポンス取得
var res = s3Client.listObjectVersions(listReq);
// S3オブジェクトリスト取得
var currentVersions = res.versions();
// 前のステップで取得したS3オブジェクトリストを連結
objVerList.addAll(currentVersions);
// 次のステップで取得を開始する位置
var nextKeyMarker = res.nextKeyMarker(); // (b, aが`false`の場合は`null`)
var nextVersionIdMarker = res.nextVersionIdMarker(); // (b, aが`false`の場合は`null`)
// 一度にすべてのS3オブジェクトを取得しきれなかった場合、S3オブジェクトリストと開始位置を更新して、このメソッドを再帰的に呼び出す
if (res.isTruncated()) { // (a)
return getAllS3Versions(bucketName, objVerList, nextKeyMarker, nextVersionIdMarker);
}
return objVerList;
}
参考資料
- ListObjectsV2Request | AWS SDK for Java API Reference - 2.27.23
- ListObjectsV2Response | AWS SDK for Java API Reference - 2.27.23
- ListObjectVersionsRequest | AWS SDK for Java API Reference - 2.27.23
- ListObjectVersionsResponse | AWS SDK for Java API Reference - 2.27.23
- ListObjectsV2Request(AWS SDK for Java)でS3のファイル一覧を取得する | Qiita