【问题标题】:AWS S3 object listingAWS S3 对象列表
【发布时间】:2015-08-23 22:03:31
【问题描述】:

我正在通过 node.js 使用 aws-sdk。我想列出指定文件夹中的图像,例如

我想列出此位置的所有文件和文件夹,但不列出文件夹(图像)内容。 aws-sdk 中有list Object function,但它也列出了所有嵌套文件。

代码如下:

var AWS = require('aws-sdk');
AWS.config.update({accessKeyId: 'mykey', secretAccessKey: 'mysecret', region: 'myregion'});
var s3 = new AWS.S3();

var params = { 
  Bucket: 'mystore.in',
  Delimiter: '',
  Prefix: 's/5469b2f5b4292d22522e84e0/ms.files' 
}

s3.listObjects(params, function (err, data) {
  if(err)throw err;
  console.log(data);
});

【问题讨论】:

  • S3 没有文件夹/文件等的概念......它只有键 - 您可以使用键中的 / 来模仿文件夹结构。
  • 请显示您目前拥有的代码
  • var AWS = require('aws-sdk'); AWS.config.update({accessKeyId: 'mykey', secretAccessKey: 'mysecret', region: 'myregion'}); var s3 = 新 AWS.S3(); var params = {桶:'mystore.in',分隔符:'',前缀:'s/5469b2f5b4292d22522e84e0/ms.files'}; s3.listObjects(params, function (err, data) { if(err)throw err; console.log(data); });
  • 请编辑问题以包含(和格式化)代码
  • 你到底想通过console.log(data)得到什么

标签: javascript node.js amazon-web-services amazon-s3


【解决方案1】:

现在使用此代码可以正常工作:

var AWS = require('aws-sdk');
AWS.config.update({accessKeyId: 'mykey', secretAccessKey: 'mysecret', region: 'myregion'});
var s3 = new AWS.S3();

var params = { 
 Bucket: 'mystore.in',
 Delimiter: '/',
 Prefix: 's/5469b2f5b4292d22522e84e0/ms.files/'
}

s3.listObjects(params, function (err, data) {
 if(err)throw err;
 console.log(data);
});

【讨论】:

  • 仅供参考 - 在listObjects 之后,我正在做getObject,我发现params 对象需要包含BucketKey,你不能保留PrefixgetObject 将出错。 Delimiter 也可能会导致问题,但我无法确定。干杯
【解决方案2】:

文件夹是虚幻的,但 S3 确实提供了一种机制来模拟它们的存在。

如果您将Delimiter 设置为/,那么每一层响应还将返回一个包含下一层“文件夹”的CommonPrefixes 数组,您将把它附加到此请求的前缀中,以检索下一层。

如果您的Prefix 是一个“文件夹”,则附加一个尾部斜杠。否则,您将发出不必要的请求,因为第一个请求将返回一个公共前缀。例如,文件夹“foo”将返回一个公共前缀“foo/”。

【讨论】:

  • 如何获取最新的对象,有没有排序选项
  • @Johne 不幸的是,目前还没有,除非您首先获取所有对象并在您身边进行排序。即使是 AWS S3 控制台也只会在您单击表头时对客户端进行排序
【解决方案3】:

我贴了一点module,其中列出了你给它的“文件夹”的内容:

s3ls({bucket: 'my-bucket-name'}).ls('/', console.log);

将打印如下内容:

{ files: [ 'funny-cat-gifs-001.gif' ],
  folders: [ 'folder/', 'folder2/' ] }

还有那个

s3ls({bucket: 'my-bucket-name'}).ls('/folder', console.log);

将打印

{ files: [ 'folder/cv.docx' ],
  folders: [ 'folder/sub-folder/' ] }

UPD:最新版本支持async/await Promise接口:

const { files, folders } = await lister.ls("/my-folder/subfolder/");

这里是s3ls.js

var _ = require('lodash');
var S3 = require('aws-sdk').S3;

module.exports = function (options) {
  var bucket = options.bucket;
  var s3 = new S3({apiVersion: '2006-03-01'});

  return {
    ls: function ls(path, callback) {
      var prefix = _.trimStart(_.trimEnd(path, '/') + '/', '/');    
      var result = { files: [], folders: [] };

      function s3ListCallback(error, data) {
        if (error) return callback(error);

        result.files = result.files.concat(_.map(data.Contents, 'Key'));
        result.folders = result.folders.concat(_.map(data.CommonPrefixes, 'Prefix'));

        if (data.IsTruncated) {
          s3.listObjectsV2({
            Bucket: bucket,
            MaxKeys: 2147483647, // Maximum allowed by S3 API
            Delimiter: '/',
            Prefix: prefix,
            ContinuationToken: data.NextContinuationToken
          }, s3ListCallback)
        } else {
          callback(null, result);
        }
      }

      s3.listObjectsV2({
        Bucket: bucket,
        MaxKeys: 2147483647, // Maximum allowed by S3 API
        Delimiter: '/',
        Prefix: prefix,
        StartAfter: prefix // removes the folder name from the file listing
      }, s3ListCallback)
    }
  };
};

【讨论】:

    【解决方案4】:

    您可以在 s3 API 参数中使用Prefix。我正在添加一个我在项目中使用的示例:

    listBucketContent: ({ Bucket, Folder }) => new Promise((resolve, reject) => {
        const params = { Bucket, Prefix: `${Folder}/` };
        s3.listObjects(params, (err, objects) => {
            if (err) {
                reject(ERROR({ message: 'Error finding the bucket content', error: err }));
            } else {
                resolve(SUCCESS_DATA(objects));
            }
        });
    })
    

    这里Bucket 是包含文件夹的存储桶的名称,Folder 是您要在其中列出文件的文件夹的名称。

    【讨论】:

    • 你可以使用 s3.listObjects(params).promise() 来避免 Promise 样板。
    • @Guido 确实如此。感谢您的改进。
    【解决方案5】:

    您也可以使用minio-js 客户端库,它是开源的并且与 AWS S3 api 兼容。

    您可以简单地使用list-objects.js 示例,更多文档可在https://docs.minio.io/docs/javascript-client-api-reference 获得。

    var Minio = require('minio')
    
    var s3Client = new Minio({
      endPoint: 's3.amazonaws.com',
      accessKey: 'YOUR-ACCESSKEYID',
      secretKey: 'YOUR-SECRETACCESSKEY'
    })
    // List all object paths in bucket my-bucketname.
    var objectsStream = s3Client.listObjects('my-bucketname', '', true)
    objectsStream.on('data', function(obj) {
      console.log(obj)
    })
    objectsStream.on('error', function(e) {
      console.log(e)
    })
    

    希望对你有帮助。

    免责声明:我为Minio工作

    【讨论】:

    • var s3Client = new Minio({ ^ TypeError: Minio is not a constructor
    【解决方案6】:

    正如 cmets 中提到的,S3 不“知道”文件夹,只知道键。您可以在键中使用 / 来模仿文件夹结构。请参阅此处了解更多信息 - http://docs.aws.amazon.com/AmazonS3/latest/UG/FolderOperations.html

    也就是说,你可以将你的代码修改成这样:

    s3.listObjects(params, function (err, data) {
      if(err) throw 
    
      //data.contents is an array of objects according to the s3 docs
      //iterate over it and see if the key contains a / - if not, it's a file (not a folder)
      var itemsThatAreNotFolders = data.contents.map(function(content){
        if(content.key.indexOf('/')<0) //if / is not in the key
            return content;
      });
    
      console.log(itemsThatAreNotFolders);
    });
    

    这将检查每个键是否包含 /

    【讨论】:

      猜你喜欢
      • 2017-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-06
      • 1970-01-01
      • 2014-07-01
      相关资源
      最近更新 更多