如何用node.js删除s3上的文件夹?

use*_*559 34 date amazon-web-services node.js

是的我知道.s3存储上没有文件夹概念.但我真的想用node.js从s3中删除一个特定的文件夹.我尝试了两种解决方案,但都没有用.我的代码如下:解决方案1:直接删除文件夹.

var key='level/folder1/folder2/';
var strReturn;
        var params = {Bucket: MyBucket};
        var s3 = new AWS.S3(params);
        s3.client.listObjects({
            Bucket: MyBucket,
            Key: key
        }, function (err, data) {
            if(err){
                strReturn="{\"status\":\"1\"}";

            }else{
                strReturn=+"{\"status\":\"0\"}";
            }
            res.send(returnJson);
            console.log('error:'+err+' data:'+JSON.stringify(data));
        });
Run Code Online (Sandbox Code Playgroud)

实际上,我在folder2下有很多文件.我可以从folder2删除单个文件,如果我定义这样的键:var key ='level/folder1/folder2/file1.txt',但是当我删除文件夹时它不起作用(key ='level/folder1/folder2/").解决方案2:当我将此文件或文件夹上传到s3时,我尝试将对期设置为对象.代码如下:

s3.client.putObject({
                Bucket: Camera_Bucket,
                Key: key,
                            ACL:'public-read', 
                Expires: 60 
            }
Run Code Online (Sandbox Code Playgroud)

但它也没有.完成上传后,我检查了该文件的属性.它表明到期日没有任何价值:

Expiry Date:none
Expiration Rule:N/A
Run Code Online (Sandbox Code Playgroud)

如何用node.js删除s3上的文件夹?

San*_*Han 52

您可以使用aws-sdk模块删除文件夹.因为你可以在文件夹为空时删除它,你应该删除它中的文件.我是这样做的.

function emptyBucket(bucketName,callback){
  var params = {
    Bucket: bucketName,
    Prefix: 'folder/'
  };

  s3.listObjects(params, function(err, data) {
    if (err) return callback(err);

    if (data.Contents.length == 0) callback();

    params = {Bucket: bucketName};
    params.Delete = {Objects:[]};

    data.Contents.forEach(function(content) {
      params.Delete.Objects.push({Key: content.Key});
    });

    s3.deleteObjects(params, function(err, data) {
      if (err) return callback(err);
      if(data.Contents.length == 1000)emptyBucket(bucketName,callback);
      else callback();
    });
  });
}
Run Code Online (Sandbox Code Playgroud)

  • 它受到1000个物体的限制.所以你应该添加一些逻辑,以防对象超过1000. (8认同)
  • `s3.deleteObjects`返回的数据中没有`data.Contents`参数.我认为它应该改为`data.Deleted`. (2认同)
  • 同意,`data.Contents`未定义.应该是`data.Deleted`. (2认同)
  • 另外,行`if(data.Contents.length == 0)callback();`需要更改为`if(data.Contents.length == 0)返回callback();`停止尝试删除什么都没有(否则AWS返回错误,你得到错误回调) (2认同)
  • 我宁愿使用`data.Contents.IsTruncated`而不是`data.Contents.length == 1000`来隐藏“内部” 1000变量... (2认同)

Emi*_*Emi 34

这是ES7中的一个实现,它带有一个async函数和使用listObjectsV2(修订后的List Objects API):

async function emptyS3Directory(bucket, dir) {
    const listParams = {
        Bucket: bucket,
        Prefix: dir
    };

    const listedObjects = await s3.listObjectsV2(listParams).promise();

    if (listedObjects.Contents.length === 0) return;

    const deleteParams = {
        Bucket: bucket,
        Delete: { Objects: [] }
    };

    listedObjects.Contents.forEach(({ Key }) => {
        deleteParams.Delete.Objects.push({ Key });
    });

    await s3.deleteObjects(deleteParams).promise();

    if (listedObjects.IsTruncated) await emptyS3Directory(bucket, dir);
}
Run Code Online (Sandbox Code Playgroud)

打电话给它:

await emptyS3Directory(process.env.S3_BUCKET, 'images/')
Run Code Online (Sandbox Code Playgroud)

  • 我认为它应该是`if(listedObjects.IsTruncated)等待emptyS3Directory(bucket,dir);`而不是`if(listedObjects.Contents.IsTruncated)等待emptyS3Directory(bucket,dir);` (3认同)
  • 干得好!请注意,这种递归有一个缺点:它会增加每次迭代中的调用堆栈深度。我建议用 `while(true) { ... if (!listedObjects.IsTruncated) { break; 包装函数的主体。}}` (2认同)

小智 5

更好的模块解决方案@aws-sdk/client-s3

private async _deleteFolder(key: string, bucketName: string): Promise<void> {
  const DeletePromises: Promise<DeleteObjectCommandOutput>[] = [];
  const { Contents } = await this.client.send(
    new ListObjectsCommand({
      Bucket: bucketName,
      Prefix: key,
    }),
  );
  if (!Contents) return;
  Contents.forEach(({ Key }) => {
    DeletePromises.push(
      this.client.send(
        new DeleteObjectCommand({
          Bucket: bucketName,
          Key,
        }),
      ),
    );
  });

  await Promise.all(DeletePromises);
}
Run Code Online (Sandbox Code Playgroud)

ListObjectsCommand返回文件夹中文件的键,即使有子文件夹