Как удалить папку на s3 с помощью node.js?

Да, я знаю. В s3-хранилище нет концепции папок. но я действительно хочу удалить определенную папку из s3 с помощью node.js. Я попробовал два решения, но оба они не работали. Мой код ниже: Решение 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));
        });

На самом деле, у меня много файлов в папке2. Я могу удалить один файл из папки2, если я определяю такой ключ: 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

Как удалить папку на s3 с помощью node.js?

Ответ 1

Вы можете использовать модуль 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();
    });
  });
}

Ответ 2

Вот реализация в ES7 с async функцией и использованием listObjectsV2 (пересмотренный API-интерфейс List Objects):

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

Чтобы назвать это:

await emptyS3Directory(process.env.S3_BUCKET, 'images/')

Ответ 3

В соответствии с принятым ответом я создал функцию обещания и возврата, так что вы можете связать ее

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

Основываясь на ответе Эми, мы черпаем вдохновение при использовании Typescript:

    public async emptyS3Directory(bucket: string, dir: string) {
    const listParams = {
        Bucket: bucket,
        Prefix: dir,
    };
    const listedObjects = await this.s3.listObjectsV2(listParams).promise();
    if (listedObjects.Contents.length === 0) {
        return;
    }
    const deleteParams = {
        Bucket: bucket,
        Delete: {
            Objects: [{Key: any}],
        },
    };
    listedObjects.Contents.forEach(({ Key }: {Key: any}) => {
        deleteParams.Delete.Objects.push( { Key } );
    });
    await this.s3.deleteObjects(deleteParams).promise();
    if (listedObjects.IsTruncated) {
        await this.emptyS3Directory(bucket, dir);
    }
}