使用Node.js AWS SDK检查S3上是否存在文件夹

11

首先,我知道实际上并不存在所谓的文件夹,但为了简便起见,我还是使用这个术语。现在我的存储桶里有很多对象。 对于某些文件夹,我可以使用getObject来查找它们是否存在,但对于大多数文件夹,我会收到“没有此键”的错误提示,尽管我明显能看到它们的存在。我还想说,我已经尝试过headObject和listObjectV2等方法,但都没有成功。

this is my params object
{
     Bucket: bucket //bucket is defined in the program
     Key: folder // defined in the program above
                 //example key - abc-1-1/00000N/30/2018.10.7.8/
                 //inside this folder are multiple files 
}

目标是查找文件夹是否存在,然后根据此进行一些处理。我看到了很多关于这个问题的答案,建议使用headObject、getObjects等等,但似乎没有一个能够工作的。

这是我的getObjects代码片段

params = {
            Bucket: bucket,
            Key: folder
        }
        s3.getObject(params, function (err, found) {

            if (err){ 
                console.log('bucket is'+bucket);
                ..........
                .....
            }
            else{
                ....
            }
            ..
            });

https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#headBucket-property - Madhav Kumar Jha
/* 此操作用于检查存储桶是否存在。*/var params = { Bucket: "acl1" }; s3.headBucket(params, function(err, data) { if (err) console.log(err, err.stack); // 发生错误 else console.log(data); // 成功响应 }); - Madhav Kumar Jha
4个回答

9
我终于为这种情况找到了一个解决方法。如果你的应用程序需要检查某个对象(“文件夹”)是否存在,并且只有在该对象(“文件夹”)实际存在时才能继续进行,你可以使用此解决方案。我相信 s3.getObject 或 s3.headObject 的工作方式存在问题,无论如何,以下是解决方案。
1)使用 s3.listObjectsV2 方法。
2)检查响应的 Contents 字段。如果为空,则您提供的前缀不存在。 以下是代码片段。
s3.listObjectsV2(params, function (err, found) {

                if (err){ 
                    console.log(err);
                    errJson = {
                        'status': -1,
                        'message': 'Error while trying to list files'
                    };
                    callback(errJson);

                } 
                else {  

                    if (found.Contents.length === 0) {

                        errJson = {
                            'status': 0,
                            'message': 'Either the files are not present at s3 or the folder is incorrect '
                        }
                        callback(errJson);
                    }
                    else{
                               .....
                    }
....
});

9
为了检查一个“文件夹”是否存在,需要检查存储桶中是否至少有一个对象的键以该文件夹的名称开头,再加上尾部斜杠。可以使用listObjectV2方法来实现这一点。
const s3 = ... // S3 client

const Bucket = 'mybucket';
const Prefix = 'myfolder/mysubfolder/';
const MaxKeys = 1; // If a single object is found, the folder exists.
const params = {
      Bucket,
      Prefix,
      MaxKeys
};

s3.listObjectsV2(params, (err, data) => {
  const folderExists = data.Contents.length > 0;

  // (folderExists == true) if the folder exists
});

注意:上述使用文件夹的定义是指至少有一个键以文件夹作为前缀。
要检测“空文件夹”,可以检查文件夹+_$folder$后缀,如此处所述。

我不太清楚为什么headObject没有表现出其他答案中描述的行为--但这是对我有效的解决方案! - ericpeters0n

2

headObject到底是怎么不起作用的?如果在您的S3存储桶中搜索目录,它应该返回以下两种情况之一:

  1. 如果请求的资源不存在(包括目录),则返回状态代码为“NotFound”的错误。
  2. 有关对象的一些详细信息的响应。

下面是一个简单的实现示例,可用于编写“check”函数:

      s3.headObject({Bucket: 'whatever-the-bucket-name-is', Key: 'directory/'}, (err, data) => {
        if (err && err.code === 'NotFound') resolve(false)
        else if (err) reject(err)
        resolve(true)
      })

希望这可以帮到你。

2
不行,尽管我已经将该目录/目录/目录/设置为键,并且它也存在于S3上,但它仍然给我一个错误。这就是我所说的,即使目录存在,这些函数也会给我一个错误。 - capedCoder
哦...你的桶里有任何内容吗?请注意,S3中的文件夹是一个“虚拟”概念,这意味着它们实际上只是对象键的前缀。更多信息请参见:https://docs.aws.amazon.com/AmazonS3/latest/user-guide/using-folders.html - Jack Thibaut
是的,我的存储桶中确实有对象。我知道对象和键的概念,并在问题中使用“文件夹”一词以简化描述。 - capedCoder
抱歉,实际问题是文件夹中是否有任何内容。如果它们是空的,亚马逊只会创建长度为零的对象,这些对象会被许多进程忽略,因此“检查”函数也很可能会忽略它们。 - Jack Thibaut
哦,好的,谢谢你澄清,顺便说一下,这个对象确实有内容。 - capedCoder
显示剩余2条评论

-2
如果您正在检查存储桶是否存在,则以下是解决方案。
var AWS = require('aws-sdk');
var s3 = {
  accessKeyId: '',
  secretAccessKey: '',
  bucketName: ''
}
AWS.config.update({
  accessKeyId: s3.accessKeyId,
  secretAccessKey: s3.secretAccessKey,
  // region: {region} - Add if needed
});

var s3bucket = new AWS.S3({ params: { Bucket: s3.bucketName } });
var options = {
  Bucket: s3.bucketName
};

function checkBucket(){
  try {
    await s3bucket.headBucket(options).promise();  
    console.log('bucket exists');
    // do the required operations here
  } catch (err) {
    if (err.statusCode === 404) {
      return error("Bucket doesn't exists.");
    }
  }
}

(async() =>{
  await checkBucket();
})()

嗨,Atishay,谢谢你,但我实际上是想检查特定目录的存在。 - capedCoder
实际上,如果目录不存在,S3 在推送时会自动创建一个。 - Atishay Jain
问题在于我的目录存在,但是这些函数给了我错误而不是数据。现在我想检查是否存在,因为我的代码需要在检查存在后进行处理,否则什么也不应该做。 - capedCoder
消息:null, 代码:'NotFound', 区域:null, 时间:2018-10-11T12:43:55.069Z, 请求ID:'E480454D2E1215B3', 扩展请求ID: 'IKtZH0T6Govkpyvw3BGcjekDzyTMZOH1gUeEJbXzcVrFKIqDJkH0cKiEqTt32+4AMiJe6YMwIXg=', CF ID:未定义, 状态码:404, 可重试:false, 重试延迟:54.259656228362594 - capedCoder
还有一堆其他的东西在错误信息里,但是字符太多了无法上传。 - capedCoder
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接