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

时间:2013-11-26 01:45:02

标签: node.js date amazon-web-services

是的,我知道。 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));
        });

实际上,我在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 
            }

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

Expiry Date:none
Expiration Rule:N/A

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

8 个答案:

答案 0 :(得分:49)

您可以使用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();
    });
  });
}

答案 1 :(得分:21)

以下是ES7中使用test: services: - name: rest-server id: edh/rest-server cmd: java -jar /path/to/my-code.jar steps: - java/maven: goals: verify maven_opts: -DrestEndpoint=http://rest-server:9000 函数并使用async(修订后的List Objects API)的实现:

listObjectsV2

要打电话:

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

答案 2 :(得分:1)

listObjectsV2 仅列出带有当前目录前缀而不带有子文件夹前缀的文件。如果要递归删除包含子文件夹的文件夹,这是源代码:https://github.com/tagspaces/tagspaces/blob/develop/app/services/objectstore-io.ts#L838

  deleteDirectoryPromise = async (path: string): Promise<Object> => {
    const prefixes = await this.getDirectoryPrefixes(path);

    if (prefixes.length > 0) {
      const deleteParams = {
        Bucket: this.config.bucketName,
        Delete: { Objects: prefixes }
      };

      return this.objectStore.deleteObjects(deleteParams).promise();
    }
    return this.objectStore
      .deleteObject({
        Bucket: this.config.bucketName,
        Key: path
      })
      .promise();
  };

  /**
   * get recursively all aws directory prefixes
   * @param path
   */
  getDirectoryPrefixes = async (path: string): Promise<any[]> => {
    const prefixes = [];
    const promises = [];
    const listParams = {
      Bucket: this.config.bucketName,
      Prefix: path,
      Delimiter: '/'
    };
    const listedObjects = await this.objectStore
      .listObjectsV2(listParams)
      .promise();

    if (
      listedObjects.Contents.length > 0 ||
      listedObjects.CommonPrefixes.length > 0
    ) {
      listedObjects.Contents.forEach(({ Key }) => {
        prefixes.push({ Key });
      });

      listedObjects.CommonPrefixes.forEach(({ Prefix }) => {
        prefixes.push({ Key: Prefix });
        promises.push(this.getDirectoryPrefixes(Prefix));
      });
      // if (listedObjects.IsTruncated) await this.deleteDirectoryPromise(path);
    }
    const subPrefixes = await Promise.all(promises);
    subPrefixes.map(arrPrefixes => {
      arrPrefixes.map(prefix => {
        prefixes.push(prefix);
      });
    });
    return prefixes;
  };

答案 3 :(得分:0)

根据接受的答案,我创建了promise返回函数,因此您可以将其链接。

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

    return S3.listObjects(params).promise().then(data => {
        if (data.Contents.length === 0) {
            throw new Error('List of objects empty.');
        }

        currentData = data;

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

        currentData.Contents.forEach(content => {
            params.Delete.Objects.push({Key: content.Key});
        });

        return S3.deleteObjects(params).promise();
    }).then(() => {
        if (currentData.Contents.length === 1000) {
            emptyBucket(bucketName, callback);
        } else {
            return true;
        }
    });
}

答案 4 :(得分:0)

根据Emi的回答,我制作了一个npm软件包,因此您不会 无需自己编写代码。代码也是用打字稿写的。

请参见https://github.com/bingtimren/s3-commons/blob/master/src/lib/deleteRecursive.ts

答案 5 :(得分:0)

您可以使用删除文件的相同方式删除空文件夹。为了删除AWS S3上的非空文件夹,您需要先通过删除其中的所有文件和文件夹将其清空。文件夹为空后,您可以将其作为常规文件删除。桶删除也一样。我们已经在名为Commandeer的此应用中实现了它,因此您可以通过GUI来实现。 enter image description here

答案 6 :(得分:0)

您可以尝试以下方法:

import { s3DeleteDir } from '@zvs001/s3-utils'
import { S3 } from 'aws-sdk'

const s3Client = new S3() 

await s3DeleteDir(s3Client, {
  Bucket: 'my-bucket',
  Prefix: `folder/`,
})

答案 7 :(得分:0)

在打字稿中使用时,接受的答案会引发错误,并且它是 deleteParams 中的对象数组。我通过以下方式修改代码使其工作。我对 Typescript 很陌生,但至少现在可以使用了。

 async function emptyS3Directory(prefix: string) {
  const listParams = {
    Bucket: "bucketName",
    Prefix: prefix, // ex. path/to/folder
  };

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

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

  const deleteParams = {
    Bucket: bucketName,
    Delete: { Objects: [] as any },
  };

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

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

  if (listedObjects.IsTruncated) await emptyS3Directory(prefix);
}