为了账号安全,请及时绑定邮箱和手机立即绑定

使用通配符匹配删除 s3 中的对象

使用通配符匹配删除 s3 中的对象

Go
江户川乱折腾 2021-11-22 18:19:25
我有以下工作代码可以从 Amazon s3 中删除一个对象params := &s3.DeleteObjectInput{        Bucket: aws.String("Bucketname"),        Key : aws.String("ObjectKey"),    }s3Conn.DeleteObjects(params)但我想要做的是使用通配符**删除文件夹下的所有文件。我知道亚马逊 s3 不会将“x/y/file.jpg”视为 x 中的文件夹 y,但我想要实现的是通过提及“x/y*”删除所有具有相同前缀的后续对象。尝试亚马逊多对象删除params := &s3.DeleteObjectsInput{        Bucket: aws.String("BucketName"),        Delete: &s3.Delete{            Objects: []*s3.ObjectIdentifier {                {                    Key : aws.String("x/y/.*"),                 },            },        },    }    result , err := s3Conn.DeleteObjects(params)我知道在 php 中它可以通过s3->delete_all_objects根据这个答案轻松完成。在 GOlang 中是否可以执行相同的操作。
查看完整描述

3 回答

?
达令说

TA贡献1821条经验 获得超6个赞

不幸的是 goamz 包没有类似于 PHP 库的delete_all_objects.


但是,delete_all_objects此处提供了 PHP 的源代码(切换源视图):http : //docs.aws.amazon.com/AWSSDKforPHP/latest/#m=AmazonS3/delete_all_objects


以下是重要的代码行:


public function delete_all_objects($bucket, $pcre = self::PCRE_ALL)

{

// Collect all matches

    $list = $this->get_object_list($bucket, array('pcre' => $pcre));


    // As long as we have at least one match...

    if (count($list) > 0)

    {

        $objects = array();


        foreach ($list as $object)

        {

            $objects[] = array('key' => $object);

        }


        $batch = new CFBatchRequest();

        $batch->use_credentials($this->credentials);


        foreach (array_chunk($objects, 1000) as $object_set)

        {

            $this->batch($batch)->delete_objects($bucket, array(

                'objects' => $object_set

            ));

        }


        $responses = $this->batch($batch)->send();

如您所见,PHP 代码实际上会在存储桶上发出 HTTP 请求以首先获取所有匹配的文件PCRE_ALL,该文件在别处定义为const PCRE_ALL = '/.*/i';.


您一次只能删除 1000 个文件,因此delete_all_objects创建了一次删除 1000 个文件的批处理功能。


您必须在 go 程序中创建相同的功能,因为 goamz 包尚不支持此功能。幸运的是,它应该只有几行代码,而且您有来自 PHP 库的指南。


完成后,可能值得提交 goamz 包的拉取请求!


查看完整回答
反对 回复 2021-11-22
?
慕森王

TA贡献1777条经验 获得超3个赞

使用mc工具,您可以:


mc rm -r --force https://BucketName.s3.amazonaws.com/x/y


它将删除所有前缀为“x/y”的对象


您可以像这样使用minio-go来实现与 Go 相同的效果:


package main


import (

    "log"


    "github.com/minio/minio-go"

)


func main() {

    config := minio.Config{

        AccessKeyID:     "YOUR-ACCESS-KEY-HERE",

        SecretAccessKey: "YOUR-PASSWORD-HERE",

        Endpoint:        "https://s3.amazonaws.com",

    }

    // find Your S3 endpoint here http://docs.aws.amazon.com/general/latest/gr/rande.html


    s3Client, err := minio.New(config)

    if err != nil {

        log.Fatalln(err)

    }

    isRecursive := true

    for object := range s3Client.ListObjects("BucketName", "x/y", isRecursive) {

        if object.Err != nil {

            log.Fatalln(object.Err)

        }

        err := s3Client.RemoveObject("BucketName", object.Key)

        if err != nil {

            log.Fatalln(err)

            continue

        }

        log.Println("Removed : " + object.Key)

    }

}


查看完整回答
反对 回复 2021-11-22
?
沧海一幻觉

TA贡献1824条经验 获得超5个赞

在游戏中有点晚,但由于我遇到了同样的问题,我创建了一个小包,您可以将其复制到您的代码库并根据需要导入。


func ListKeysInPrefix(s s3iface.S3API, bucket, prefix string) ([]string, error) {

    res, err := s.Client.ListObjectsV2(&s3.ListObjectsV2Input{

        Bucket: aws.String(bucket),

        Prefix: aws.String(prefix),

    })

    if err != nil {

        return []string{}, err

    }


    var keys []string

    for _, key := range res.Contents {

        keys = append(keys, *key.Key)

    }

    return keys, nil

}


func createDeleteObjectsInput(keys []string) *s3.Delete {

    rm := []*s3.ObjectIdentifier{}

    for _, key := range keys {

        rm = append(rm, &s3.ObjectIdentifier{Key: aws.String(key)})

    }

    return &s3.Delete{Objects: rm, Quiet: aws.Bool(false)}

}


func DeletePrefix(s s3iface.S3API, bucket, prefix string) error {

    keys, err := s.ListKeysInPrefix(bucket, prefix)

    if err != nil {

        panic(err)

    }


    _, err = s.Client.DeleteObjects(&s3.DeleteObjectsInput{

        Bucket: aws.String(bucket),

        Delete: s.createDeleteObjectsInput(keys),

    })


    if err != nil {

        return err

    }

    return nil

}

因此,如果您有一个名为“somebucket”的存储桶,其结构如下:s3://somebucket/foo/some-prefixed-folder/bar/test.txt并且想从some-prefixed-folder以后删除,用法将是:


func main() {

    // create your s3 client here

    // client := ....

    err := DeletePrefix(client, "somebucket", "some-prefixed-folder")

    if err != nil {

        panic(err)

    }

}

此实现仅允许从给定的前缀中删除最多 1000 个条目,ListObjectsV2但它是分页的,因此需要添加功能以保持刷新结果,直到结果 < 1000。


查看完整回答
反对 回复 2021-11-22
  • 3 回答
  • 0 关注
  • 180 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信