web-dev-qa-db-fra.com

Liste des fichiers dans un "dossier" spécifique d'un compartiment AWS S3

Je dois répertorier tous les fichiers contenus dans un certain dossier de mon compartiment S3.

La structure du dossier est la suivante

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

J'ai des fichiers liés aux utilisateurs et des fichiers liés au contact d'un certain utilisateur . Je dois répertorier les deux.

Pour lister les fichiers, j'utilise ce code:

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

Pour lister les fichiers d'un utilisateur, j'utilise ce préfixe: 

users/<user-id>/ 

et j'obtiens correctement tous les fichiers du répertoire à l'exception du sous-répertoire contacts, par exemple:

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

Pour lister les fichiers d'un contact utilisateur spécifique, j'utilise ce préfixe: 

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

mais dans ce cas, je reçois également le répertoire lui-même en tant qu'objet retourné:

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

Pourquoi ai-je ce comportement? Quelle est la différence entre les deux demandes d'inscription? Je n'ai besoin de lister que les fichiers du répertoire, à l'exclusion des sous-répertoires.

29
davioooh

Tout dans S3 est un objet. Pour vous, il peut s'agir de fichiers et de dossiers. Mais pour S3, ce ne sont que des objets.

Les objets qui se terminent par le délimiteur (/ dans la plupart des cas) sont généralement perçus comme un dossier, mais ce n'est pas toujours le cas. Cela dépend de l'application. Encore une fois, dans votre cas, vous interprétez cela comme un dossier. S3 n'est pas. C'est juste un autre objet.

Dans votre cas ci-dessus, l'objet users/<user-id>/contacts/<contact-id>/ existe dans S3 en tant qu'objet distinct, contrairement à l'objet users/<user-id>/. C'est la différence dans vos réponses. Pourquoi ils sont comme ça, on ne peut pas vous le dire, mais quelqu'un a fabriqué l'objet dans un cas et ne l'a pas fait dans l'autre. Vous ne le voyez pas dans AWS Management Console parce que la console l'interprète comme un dossier et vous le cache.

Puisque S3 ne considère que ces objets comme des objets, il ne vous "exclut" pas. Il appartient au client de gérer les objets comme il se doit.

Votre solution

Puisque vous êtes celui qui ne veut pas les objets de dossier, vous pouvez l'exclure vous-même en vérifiant le dernier caractère pour un /. Si c'est le cas, ignorez l'objet de la réponse.

18
Matt Houser

Bien que tout le monde dise qu'il n'y a pas de répertoires et de fichiers dans s3, mais uniquement des objets (et des seaux), ce qui est absolument vrai, je suggérerais de tirer parti des préfixes communs décrits dans this answer ..__ pouvez faire ce qui suit pour obtenir la liste des "dossiers" (préfixes communs) et des "fichiers" (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());
}

Dans votre cas, pour objectSummaries (fichiers), il devrait renvoyer (en cas de préfixe correct): 
users/id-utilisateur/contacts/id-contact/fichier1.txt
users/id-utilisateur/contacts/id-contact/fichier2.txt

pour commonPrefixes:
users/id-utilisateur/contacts/id-contact/

18
Vic K

Comme d'autres l'ont déjà dit, tout dans S3 est un objet. Pour vous, il peut s'agir de fichiers et de dossiers. Mais pour S3, ce ne sont que des objets.

Si vous n'avez pas besoin d'objets se terminant par un '/', vous pouvez les supprimer en toute sécurité, par exemple. via REST api ou AWS Java SDK (je suppose que vous avez un accès en écriture). Vous ne perdrez pas les "fichiers imbriqués" (il n'y a pas de fichiers, vous ne perdrez donc pas les objets dont le nom est précédé de la clé que vous supprimez)

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

Veuillez noter que j'utilise ProfileCredentialsProvider pour que mes demandes ne soient pas anonymes. Sinon, vous ne pourrez pas supprimer un objet. Ma clé de conservation AWS est stockée dans le fichier ~/.aws/credentials.

0
MrKiller21

vous pouvez vérifier le type. s3 a un application/x-directory spécial

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

S3 ne possède pas de répertoires. Vous pouvez répertorier les fichiers de manière pseudo-répertoire comme vous l'avez montré, mais il n'y a pas de répertoire "fichier".
Vous pouvez avoir créé par inadvertance un fichier de données appelé users/<user-id>/contacts/<contact-id>/.

0
Magnus