Existe-t-il une bibliothèque client Amazon S3 pour Node.js qui autorise la liste de tous les fichiers dans le compartiment S3?
Les plus connus aws2js et knox ne semblent pas avoir cette fonctionnalité.
En fait, aws2js prend en charge la liste des objets d'un compartiment à un niveau inférieur via l'appel de la méthode s3.get()
. Pour ce faire, il faut passer le paramètre prefix
qui est documenté sur page de l'API Amazon S3 REST :
var s3 = require('aws2js').load('s3', awsAccessKeyId, awsSecretAccessKey);
s3.setBucket(bucketName);
var folder = encodeURI('some/path/to/S3/folder');
var url = '?prefix=' + folder;
s3.get(url, 'xml', function (error, data) {
console.log(error);
console.log(data);
});
La variable data
de l'extrait de code ci-dessus contient une liste de tous les objets du compartiment bucketName
.
Utilisation de la commande aws-sdk :
var allKeys = [];
function listAllKeys(marker, cb)
{
s3.listObjects({Bucket: s3bucket, Marker: marker}, function(err, data){
allKeys.Push(data.Contents);
if(data.IsTruncated)
listAllKeys(data.NextMarker, cb);
else
cb();
});
}
voir s3.listObjects
Edit 2017: Même idée de base, mais listObjectsV2( ... )
est maintenant recommandé et utilise une ContinuationToken
(voir s3.listObjectsV2 ):
var allKeys = [];
function listAllKeys(token, cb)
{
var opts = { Bucket: s3bucket };
if(token) opts.ContinuationToken = token;
s3.listObjectsV2(opts, function(err, data){
allKeys = allKeys.concat(data.Contents);
if(data.IsTruncated)
listAllKeys(data.NextContinuationToken, cb);
else
cb();
});
}
Voici le code de nœud que j'ai écrit pour assembler les objets S3 à partir de listes tronquées.
var params = {
Bucket: <yourbucket>,
Prefix: <yourprefix>,
};
var s3DataContents = []; // Single array of all combined S3 data.Contents
function s3Print() {
if (program.al) {
// --al: Print all objects
console.log(JSON.stringify(s3DataContents, null, " "));
} else {
// --b: Print key only, otherwise also print index
var i;
for (i = 0; i < s3DataContents.length; i++) {
var head = !program.b ? (i+1) + ': ' : '';
console.log(head + s3DataContents[i].Key);
}
}
}
function s3ListObjects(params, cb) {
s3.listObjects(params, function(err, data) {
if (err) {
console.log("listS3Objects Error:", err);
} else {
var contents = data.Contents;
s3DataContents = s3DataContents.concat(contents);
if (data.IsTruncated) {
// Set Marker to last returned key
params.Marker = contents[contents.length-1].Key;
s3ListObjects(params, cb);
} else {
cb();
}
}
});
}
s3ListObjects(params, s3Print);
Faites attention à la documentation de listObject de NextMarker, qui est toujours présente dans l'objet de données renvoyé, ET _ N'EST PAS. Je ne l'utilise donc pas du tout dans le code ci-dessus ...
NextMarker - (String) Lorsque la réponse est tronquée (la valeur de l'élément IsTruncated Dans la réponse est true), vous pouvez utiliser le nom de la clé dans ce champ en tant que marqueur dans la requête suivante pour obtenir le prochain jeu de objets. Amazon S3 répertorie les objets par ordre alphabétique. Remarque: Ceci L'élément n'est renvoyé que si vous avez le paramètre de demande de délimiteur spécifié. Si la réponse n'inclut pas le NextMarker et que c'est tronqué, vous pouvez utilisez la valeur de la dernière clé dans la réponse en tant que marqueur dans la requête suivante pour obtenir le prochain ensemble d'objets clés.
L'ensemble du programme a maintenant été placé dans https://github.com/kenklin/s3list .
Publié knox-copy alors que je ne trouvais pas une bonne solution existante. Enveloppe tous les détails de la pagination de l'API Rest dans un flux de noeud familier:
var knoxCopy = require('knox-copy');
var client = knoxCopy.createClient({
key: '<api-key-here>',
secret: '<secret-here>',
bucket: 'mrbucket'
});
client.streamKeys({
// omit the prefix to list the whole bucket
prefix: 'buckets/of/fun'
}).on('data', function(key) {
console.log(key);
});
Si vous répertoriez moins de 1000 fichiers, une seule page fonctionnera:
client.listPageOfKeys({
prefix: 'smaller/bucket/o/fun'
}, function(err, page) {
console.log(page.Contents); // <- Here's your list of files
});
C'est une vieille question et je suppose que le SDK AWS JS a beaucoup changé depuis qu'il a été posé. Voici encore une autre façon de le faire ces jours-ci:
s3.listObjects({Bucket:'mybucket', Prefix:'some-pfx'}).
on('success', function handlePage(r) {
//... handle page of contents r.data.Contents
if(r.hasNextPage()) {
// There's another page; handle it
r.nextPage().on('success', handlePage).send();
} else {
// Finished!
}
}).
on('error', function(r) {
// Error!
}).
send();
Meekohi a fourni une très bonne réponse, mais la (nouvelle) documentation indique que NextMarker peut être indéfini. Dans ce cas, vous devez utiliser la dernière clé comme marqueur.
Donc, son exemple de code peut être changé en:
var allKeys = [];
function listAllKeys(marker, cb) {
s3.listObjects({Bucket: s3bucket, Marker: marker}, function(err, data){
allKeys.Push(data.Contents);
if(data.IsTruncated)
listAllKeys(data.NextMarker || data.Contents[data.Contents.length-1].Key, cb);
else
cb();
});
}
Je ne peux pas commenter la réponse originale car je n’ai pas la réputation requise. Toutes mes excuses pour la mauvaise marge bénéficiaire.
J'ai fini par créer une fonction wrapper autour de ListObjectsV2, fonctionne de la même manière et prend les mêmes paramètres mais fonctionne de manière récursive jusqu'à ce que IsTruncated = false et renvoie toutes les clés trouvées sous forme de tableau dans le second paramètre de la fonction de rappel
const AWS = require('aws-sdk')
const s3 = new AWS.S3()
function listAllKeys(params, cb)
{
var keys = []
if(params.data){
keys = keys.concat(params.data)
}
delete params['data']
s3.listObjectsV2(params, function(err, data){
if(err){
cb(err)
} else if (data.IsTruncated) {
params['ContinuationToken'] = data.NextContinuationToken
params['data'] = data.Contents
listAllKeys(params, cb)
} else {
keys = keys.concat(data.Contents)
cb(null,keys)
}
})
}
Si vous souhaitez obtenir la liste des clés uniquement dans un dossier spécifique à l'intérieur d'un compartiment S3, cela vous sera utile.
Fondamentalement, la fonction listObjects
commencera la recherche à partir de la Marker
que nous avons définie et cherchera jusqu'au maxKeys: 1000
comme limite. il recherchera donc un à un les dossiers et vous obtiendra les 1000 premières clés qu’il trouvera dans différents dossiers d’un compartiment.
Considérez que j'ai plusieurs dossiers dans mon compartiment avec le préfixe prod/some date/, Ex: prod/2017/05/12/ ,prod/2017/05/13/,etc
.
Je veux récupérer la liste des objets (noms de fichiers) uniquement dans le dossier prod/2017/05/12/
, puis je spécifierai prod/2017/05/12/
comme début et prod/2017/05/13/
[votre nom de dossier suivant] comme fin et le code que je brise la boucle lorsque je rencontre la fin.
Chaque Key
in data.Contents
ressemblera à ceci.
{ Key: 'prod/2017/05/13/4bf2c675-a417-4c1f-a0b4-22fc45f99207.jpg',
LastModified: 2017-05-13T00:59:02.000Z,
ETag: '"630b2sdfsdfs49ef392bcc16c833004f94ae850"',
Size: 134236366,
StorageClass: 'STANDARD',
Owner: { }
}
Code:
var list = [];
function listAllKeys(s3bucket, start, end) {
s3.listObjects({
Bucket: s3bucket,
Marker: start,
MaxKeys: 1000,
}, function(err, data) {
if (data.Contents) {
for (var i = 0; i < data.Contents.length; i++) {
var key = data.Contents[i].Key; //See above code for the structure of data.Contents
if (key.substring(0, 19) != end) {
list.Push(key);
} else {
break; // break the loop if end arrived
}
}
console.log(list);
console.log('Total - ', list.length);
}
});
}
listAllKeys('BucketName', 'prod/2017/05/12/', 'prod/2017/05/13/');
Sortie:
[ 'prod/2017/05/12/05/4bf2c675-a417-4c1f-a0b4-22fc45f99207.jpg',
'prod/2017/05/12/05/a36528b9-e071-4b83-a7e6-9b32d6bce6d8.jpg',
'prod/2017/05/12/05/bc4d6d4b-4455-48b3-a548-7a714c489060.jpg',
'prod/2017/05/12/05/f4b8d599-80d0-46fa-a996-e73b8fd0cd6d.jpg',
... 689 more items ]
Total - 692
Bien que, techniquement, la réponse de @ Meekohi fonctionne, j’ai assez de chagrin avec la partie S3 du kit SDK AWS pour NodeJS. Après toutes les difficultés précédentes avec des modules tels que aws-sdk
, s3
, knox
, j'ai décidé d'installer s3cmd via le gestionnaire de paquets du système d'exploitation et de Shell-out à l'aide de child_process
Quelque chose comme:
var s3cmd = new cmd_exec('s3cmd', ['ls', filepath, 's3://'+inputBucket],
function (me, data) {me.stdout += data.toString();},
function (me) {me.exit = 1;}
);
response.send(s3cmd.stdout);
(Utilisation de l'implémentation cmd_exec
de cette question )
Cette approche fonctionne très bien, y compris pour d’autres problèmes, comme le téléchargement de fichiers.