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

时间:2015-11-19 18:07:16

标签: go amazon-s3 aws-sdk

我有以下工作代码从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 *”删除具有相同前缀的所有后续对象。试过amazon multi object delete

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 轻松完成this answer。在GOlang中可以采取相同的行动。

3 个答案:

答案 0 :(得分:3)

不幸的是goamz包没有类似于PHP库delete_all_objects的方法。

但是,此处提供了PHP delete_all_objects的源代码(切换源视图):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';定义为delete_all_objects

您一次只能删除1000个文件,因此Nov 19, 2015 9:07:50 PM org.springframework.web.servlet.PageNotFound noHandlerFound WARNING: No mapping found for HTTP request with URI [/SoccerSpringMaven3/springSoccer/users] in DispatcherServlet with name 'springSoccer' 会创建一个批处理功能,一次删除1000个文件。

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

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

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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

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

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