txt proyecto nodejs node manejo leer guardar español escribir crear codigofacilito archivos archivo abrir node.js amazon-s3

proyecto - Node.js y Amazon S3: ¿cómo iterar a través de todos los archivos en un cubo?



node js codigofacilito (10)

¿Hay alguna biblioteca de cliente de Amazon S3 para Node.js que permita la inclusión de todos los archivos en el depósito S3?

Los aws2js y knox más conocidos no parecen tener esta funcionalidad.


Aquí está el código del nodo que escribí para ensamblar los objetos S3 de las listas truncadas.

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);

Preste atención a s3.listObjects documentación de ListObject de NextMarker, que NO siempre está presente en el objeto de datos devuelto, por lo que no lo uso en absoluto en el código anterior ...

NextMarker - (String) Cuando la respuesta se trunca (el valor del elemento IsTruncated en la respuesta es verdadero), puede usar el nombre de la clave en este campo como marcador en la solicitud posterior para obtener el siguiente conjunto de objetos. Amazon S3 enumera los objetos en orden alfabético. Nota: este elemento se devuelve solo si tiene especificado un parámetro de solicitud de delimitador. Si la respuesta no incluye el NextMarker y se trunca, puede usar el valor de la última clave en la respuesta como marcador en la solicitud subsiguiente para obtener el siguiente conjunto de claves del objeto .

El programa completo ahora se ha enviado a https://github.com/kenklin/s3list .


Aunque la respuesta de @Meekohi funciona técnicamente, he tenido suficiente dolor con la porción S3 del AWS SDK para NodeJS. Después de todos los problemas anteriores con módulos como aws-sdk , s3 , knox , decidí instalar s3cmd través del gestor de paquetes del sistema operativo y child_process utilizando child_process

Algo como:

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);

(Usando la implementación cmd_exec de esta pregunta )

Este enfoque funciona muy bien, incluso para otras cuestiones problemáticas como la carga de archivos.


De hecho, aws2js admite la lista de objetos en un depósito en un nivel bajo mediante la llamada al método s3.get() . Para hacerlo, uno debe pasar el parámetro de prefix que está documentado en la página de la API de REST de Amazon S3 :

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 de data en el fragmento de arriba contiene una lista de todos los objetos en el bucketName .


Esta es una vieja pregunta y creo que AWS JS SDK ha cambiado mucho desde que se solicitó. Aquí hay otra forma de hacerlo en estos días:

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();


La forma más limpia de hacerlo fue a través de la ejecución de s3cmd desde mi script de nodo como este (El ejemplo aquí es para eliminar archivos recursivamente):

var exec = require(''child_process'').exec; var child; var bucket = "myBucket"; var prefix = "myPrefix"; // this parameter is optional var command = "s3cmd del -r s3://" + bucket + "/" + prefix; child = exec(command, {maxBuffer: 5000 * 1024}, function (error, stdout, stderr) { // the maxBuffer is here to avoid the maxBuffer node process error console.log(''stdout: '' + stdout); if (error !== null) { console.log(''exec error: '' + error); } });


Meekohi brindó una muy buena respuesta, pero la (nueva) documentación indica que NextMarker puede estar indefinido. Cuando este es el caso, debe usar la última tecla como marcador.

Entonces su codesample puede ser cambiado a:

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(); }); }

No pude comentar la respuesta original ya que no tengo la reputación requerida. Disculpas por el mal mark-up por cierto.


Si desea obtener una lista de claves solo dentro de una carpeta específica dentro de un Bucket S3, esto será útil.

Básicamente, la función listObjects comenzará a buscar desde el Marker que establezcamos y buscará hasta maxKeys: 1000 como límite. por lo que buscará una por una carpeta y obtendrá las primeras 1000 claves que encuentre de una carpeta diferente en un cubo.

Considere que tengo muchas carpetas dentro de mi cubo con prefijo como prod/some date/, Ex: prod/2017/05/12/ ,prod/2017/05/13/,etc

Quiero buscar una lista de objetos (nombres de archivo) solo dentro de la carpeta prod/2017/05/12/ luego especificaré prod/2017/05/12/ como inicio y prod/2017/05/13/ [su próxima carpeta nombre] como mi final y en código estoy rompiendo el ciclo cuando encuentro el final.

Cada Key en data.Contents se verá así.

{ 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: { } }

Código:

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/'');

Salida:

[ ''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


Usando el aws-sdk oficial:

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(); }); }

ver s3.listObjects

Edición 2017 : la misma idea básica, pero ahora se recomienda listObjectsV2( ... ) y utiliza un ContinuationToken (consulte 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(); }); }


Usando la nueva API s3.listObjectsV2 la solución recursiva será:

S3Dataset.prototype.listFiles = function(params,callback) { var self=this; var options = { }; for (var attrname in params) { options[attrname] = params[attrname]; } var results=[]; var s3=self.s3Store.GetInstance(); function listAllKeys(token, callback) { var opt={ Bucket: self._options.s3.Bucket, Prefix: self._options.s3.Key, MaxKeys: 1000 }; if(token) opt.ContinuationToken = token; s3.listObjectsV2(opt, (error, data) => { if (error) { if(self.logger) this.logger.error("listFiles error:", error); return callback(error); } else { for (var index in data.Contents) { var bucket = data.Contents[index]; if(self.logger) self.logger.debug("listFiles Key: %s LastModified: %s Size: %s", bucket.Key, bucket.LastModified, bucket.Size); if(bucket.Size>0) { var Bucket=self._options.s3.Bucket; var Key=bucket.Key; var components=bucket.Key.split(''/''); var name=components[components.length-1]; results.push({ name: name, path: bucket.Key, mtime: bucket.LastModified, size: bucket.Size, sizehr: formatSizeUnits(bucket.Size) }); } } if( data.IsTruncated ) { // truncated page return listAllKeys(data.NextContinuationToken, callback); } else { return callback(null,results); } } }); } return listAllKeys.apply(this,['''',callback]); };

dónde

function formatSizeUnits(bytes){ if (bytes>=1099511627776) {bytes=(bytes/1099511627776).toFixed(4)+'' PB'';} else if (bytes>=1073741824) {bytes=(bytes/1073741824).toFixed(4)+'' GB'';} else if (bytes>=1048576) {bytes=(bytes/1048576).toFixed(4)+'' MB'';} else if (bytes>=1024) {bytes=(bytes/1024).toFixed(4)+'' KB'';} else if (bytes>1) {bytes=bytes+'' bytes'';} else if (bytes==1) {bytes=bytes+'' byte'';} else {bytes=''0 byte'';} return bytes; }//formatSizeUnits


knox-copy publicado cuando no pude encontrar una buena solución existente. Encapsula todos los detalles de paginación de la API Rest en una secuencia de nodos familiar:

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 publica menos de 1000 archivos, una sola página funcionará:

client.listPageOfKeys({ prefix: ''smaller/bucket/o/fun'' }, function(err, page) { console.log(page.Contents); // <- Here''s your list of files });