web-dev-qa-db-ja.com

AWS S3バケットの特定の「フォルダー」にあるファイルの一覧表示

S3バケットに含まれる特定のフォルダーに含まれるすべてのファイルをリストする必要があります。

フォルダー構造は次のとおりです

/my-bucket/users/<user-id>/contacts/<contact-id>

ユーザーに関連するファイルと、特定のユーザーの連絡先に関連するファイルがあります。両方をリストする必要があります。

このコードを使用しているファイルを一覧表示するには:

ListObjectsRequest listObjectsRequest = new ListObjectsRequest().withBucketName("my-bucket")
                .withPrefix("some-prefix").withDelimiter("/");
ObjectListing objects = transferManager.getAmazonS3Client().listObjects(listObjectsRequest);

特定のユーザーのファイルをリストするには、このプレフィックスを使用しています。

users/<user-id>/

contactsサブディレクトリを除くディレクトリ内のすべてのファイルを正しく取得しています。次に例を示します。

users/<user-id>/file1.txt
users/<user-id>/file2.txt
users/<user-id>/file3.txt

代わりに、特定のユーザーの連絡先のファイルをリストするには、このプレフィックスを使用しています。

users/<user-id>/contacts/<contact-id>/

しかし、この場合、返されたオブジェクトとしてディレクトリ自体も取得しています:

users/<user-id>/contacts/<contact-id>/file1.txt
users/<user-id>/contacts/<contact-id>/file2.txt
users/<user-id>/contacts/<contact-id>/

なぜこの振る舞いをするのですか? 2つのリスティングリクエストの違いは何ですか?サブディレクトリを除き、ディレクトリ内のファイルのみをリストする必要があります。

40
davioooh

S3のすべてはオブジェクトです。あなたにとって、それはファイルとフォルダかもしれません。しかし、S3にとって、それらは単なるオブジェクトです。

区切り文字(ほとんどの場合/)で終わるオブジェクトは通常フォルダーとして認識されますが、常にそうであるとは限りません。それはアプリケーションに依存します。繰り返しますが、あなたの場合、それはフォルダーとして解釈しています。 S3はそうではありません。それは単なる別のオブジェクトです。

上記の場合、オブジェクトusers/<user-id>/contacts/<contact-id>/はS3に別個のオブジェクトとして存在しますが、オブジェクトusers/<user-id>/は存在しません。それがあなたの反応の違いです。なぜそうなのか、私たちはあなたに伝えることはできませんが、誰かがオブジェクトを作成したケースとそうでないケースがありました。コンソールはそれをフォルダとして解釈し、あなたからそれを隠しているため、AWSマネジメントコンソールには表示されません。

S3はこれらのものをオブジェクトと見なすだけなので、特定のものを「除外」しません。オブジェクトを処理する必要があるので、オブジェクトを処理するのはクライアント次第です。

あなたの解決策

あなたはフォルダオブジェクトを必要としないので、/の最後の文字をチェックすることで自分でフォルダオブジェクトを除外できます。そうである場合、応答からオブジェクトを無視します。

23
Matt Houser

S3にはディレクトリやファイルはなく、オブジェクト(およびバケット)のみが存在するということは誰もが言っていますが、これは this answerで説明されているCommonPrefixesを利用することをお勧めします。そのため、以下を実行して、「フォルダー」(commonPrefixes)および「ファイル」(objectSummaries)のリストを取得できます。

ListObjectsV2Request req = new ListObjectsV2Request().withBucketName(bucket.getName()).withPrefix(prefix).withDelimiter(DELIMITER);
ListObjectsV2Result listing = s3Client.listObjectsV2(req);
for (String commonPrefix : listing.getCommonPrefixes()) {
        System.out.println(commonPrefix);
}
for (S3ObjectSummary summary: listing.getObjectSummaries()) {
    System.out.println(summary.getKey());
}

あなたの場合、objectSummaries(ファイル)の場合は(正しいプレフィックスの場合)を返す必要があります。
users/user-id/contacts/contact-id/file1.txt
users/user-id/contacts/contact-id/file2.txt

commonPrefixesの場合:
users/user-id/contacts/contact-id /

26
Vic K

他の人がすでに言ったように、S3のすべてはオブジェクトです。あなたにとって、それはファイルとフォルダかもしれません。しかし、S3にとって、それらは単なるオブジェクトです。

「/」で終わるオブジェクトが必要ない場合は、安全に削除できます。 REST apiまたはAWS Java SDK経由(書き込みアクセス権があると仮定します)。 「ネストされたファイル」は失われません(ファイルがないため、名前に削除するキーがプレフィックスとして付いているオブジェクトは失われません)

AmazonS3 amazonS3 = AmazonS3ClientBuilder.standard().withCredentials(new ProfileCredentialsProvider()).withRegion("region").build();
amazonS3.deleteObject(new DeleteObjectRequest("my-bucket", "users/<user-id>/contacts/<contact-id>/"));

リクエストが匿名にならないように、私はProfileCredentialsProviderを使用していることに注意してください。そうしないと、オブジェクトを削除できません。 AWSキーを〜/ .aws/credentialsファイルに保存します。

0
MrKiller21

タイプを確認できます。 s3には特別なapplication/x-directoryがあります

bucket.objects({:delimiter=>"/", :prefix=>"f1/"}).each { |obj| p obj.object.content_type }
0
Yaroslav Malyk

S3にはディレクトリがありませんが、デモのように擬似ディレクトリの方法でファイルを一覧表示できますが、ディレクトリごとの「ファイル」はありません。
users/<user-id>/contacts/<contact-id>/というデータファイルを誤って作成した可能性があります。

0
Magnus