Список файлов в определенной "папке" ведра 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>/
Почему я получаю такое поведение? Какая разница между двумя запросами на листинг? Мне нужно указать только файлы в каталоге, исключая подкаталоги.
Ответы
Ответ 1
Все в S3 является объектом. Для вас это могут быть файлы и папки. Но для S3 они просто объекты.
Объекты, которые заканчиваются разделителем (/
в большинстве случаев), обычно воспринимаются как папка, но это не всегда так. Это зависит от приложения. Опять же, в вашем случае вы интерпретируете его как папку. S3 - нет. Это просто еще один объект.
В вашем случае выше users/<user-id>/contacts/<contact-id>/
объектов users/<user-id>/contacts/<contact-id>/
существуют в S3 как отдельный объект, но users/<user-id>/
объекта users/<user-id>/
не работают. Это разница в ваших ответах. Почему они такие, мы не можем вам сказать, но кто-то сделал объект в одном случае, а другой не был. Вы не видите его в консоли управления AWS, потому что консоль интерпретирует его как папку и скрывает его от вас.
Поскольку S3 просто видит эти вещи как объекты, он не "исключает" определенные вещи для вас. Это до клиента, чтобы иметь дело с объектами, как с ними нужно иметь дело.
Ваше решение
Поскольку вы не хотите, чтобы объекты папок, вы можете исключить его самостоятельно, проверив последний символ для /
. Если это так, то игнорируйте объект из ответа.
Ответ 2
Хотя все говорят, что в s3 нет каталогов и файлов, но только объекты (и ведра), что абсолютно верно, я бы предложил использовать CommonPrefixes, описанные в этот ответ.
Итак, вы можете сделать следующее, чтобы получить список "папок" (commonPrefixes) и "files" (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 (файлов) он должен вернуться (в случае правильного префикса):
пользователи/идентификатор пользователя/контакты/контакт-ID/file1.txt
пользователи/идентификатор пользователя/контакты/контакт-ID/file2.txt
для общих префиксов:
пользователи/идентификатор пользователя/контакты/контакт-идентификатор/
Ответ 3
S3 не имеет каталогов, в то время как вы можете перечислить файлы в псевдо-каталоге, как вы продемонстрировали, нет каталога "файл" per-se.
Вы можете непреднамеренно создать файл данных с именем users/<user-id>/contacts/<contact-id>/
.
Ответ 4
вы можете проверить тип. s3 имеет специальное приложение /x-каталог
bucket.objects({:delimiter=>"/", :prefix=>"f1/"}).each { |obj| p obj.object.content_type }
Ответ 5
Как уже говорили другие, все в 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.