【问题标题】:How I can safely check if file exists in S3 bucket using go in lambda?如何使用 go in lambda 安全地检查 S3 存储桶中是否存在文件?
【发布时间】:2022-03-19 21:17:05
【问题描述】:

我正在为我的项目开发一项服务,该服务用于同步 AWS 中的 Lambdas 工作。这个想法是编写一个 TrackerFile 模块,它将在 S3 上存储结构。每次我使用tracker时,我都会检查是否有一个文件名称分配给被调用的tracker。

我不知道如何安全地检查 S3 上是否存在具有给定名称的文件。如果文件存在,您能否展示一段能够返回 (bool, err) 的示例代码,其中 bool 为 True?

【问题讨论】:

标签: file go amazon-s3 aws-lambda


【解决方案1】:

确保您拥有以下权限: "s3:GetObject", "s3:ListBucket",

关于安全性,AWS 刚刚为 S3 引入了强一致性

s3svc = s3.New(sess)
     
func keyExists(bucket string, key string) (bool, error) {
        _, err := S3Svc().HeadObject(&s3.HeadObjectInput{
            Bucket: aws.String(bucket),
            Key:    aws.String(key),
        })
        if err != nil {
            if aerr, ok := err.(awserr.Error); ok {
                switch aerr.Code() {            
                case "NotFound": // s3.ErrCodeNoSuchKey does not work, aws is missing this error code so we hardwire a string
                    return false, nil
                default:
                    return false, err
                }
            }
            return false, err
        }
        return true, nil
    }

【讨论】:

    【解决方案2】:

    如果您使用适用于 Go V2 的 AWS 开发工具包:

    import (
        ...
        awshttp "github.com/aws/aws-sdk-go-v2/aws/transport/http"
        ...
    )
    
    func uploaded(ctx context.Context, client *s3.Client, bucket string, key string) (bool, error) {
        _, err := client.HeadObject(ctx, &s3.HeadObjectInput{
            Bucket: aws.String(bucket),
            Key:    aws.String(key),
        })
        if err != nil {
            var responseError *awshttp.ResponseError
            if errors.As(err, &responseError) && responseError.ResponseError.HTTPStatusCode() == http.StatusNotFound {
                return false, nil
            }
            return false, err
        }
        return true, nil
    }
    

    Handling Errors in the AWS SDK for Go V2

    【讨论】:

    • 优秀的答案!你知道我们如何在 HeadObject 方法中得到错误吗?
    • 我的意思是,一个与 not found 不同的错误
    • 谢谢!是的,这是可能的。您可以探索适用于 Go V2 的 AWS 开发工具包并检查可用的错误。另外,请参阅此文档以了解处理错误的新方法:Handling Errors in the AWS SDK for Go V2
    【解决方案3】:

    你可以试试这个代码get object metadata:

    sess, err := session.NewSession(&aws.Config{
        Region: aws.String("your-region"),
    })
    
    if err != nil {
        //handle error here
    }
    
    svc := s3.New(session.Must(sess, err))
    output, err := svc.HeadObject(&s3.HeadObjectInput{
        Bucket: aws.String("bucket_name"),
        Key:    aws.String("object_key"),
    })
    
    if err != nil {
        //handle error here
    }
    
    fmt.Println(output.LastModified) //do something with metadata
    

    【讨论】:

    • 这对并发写入肯定是不安全的。
    • @mh-cbon 我同意,但没有人知道 R.Slaby 在“安全”下是什么意思。顺便说一句,即使 S3 对象是并发写入的,为什么还需要并发获取它的元数据呢?
    • 通常您在某种分布式处理中使用s3,根据实现要求,它们可能会竞争相同的资源,因此我的评论。和你一样,我不清楚 OP q 中的安全意味着什么。
    【解决方案4】:

    只需参考 AWS API S3 HeadObject 方法:AWS API documentation。 如果缺少对象,它将返回状态码404

    HEAD 请求与对象上的 GET 操作具有相同的选项。这 响应与 GET 响应相同,只是没有 响应体。因此,如果 HEAD 请求生成 错误,它返回一个通用的 404 Not Found 或 403 Forbidden 代码。

    import (
      "context"
      "github.com/aws/aws-sdk-go-v2/aws"
      "github.com/aws/aws-sdk-go-v2/service/s3"
      "log"
    )
    
    func IsObjectExistsInS3Bucket(bucketName string, objectKey string) bool{
      _, err := executeHeadObjectMethodOnS3Api(bucketName, objectKey)
      return ! handleErrorOnS3HeadObjectAction(bucketName, objectKey, err)
    }
    
    func executeHeadObjectMethodOnS3Api(bucketName string, objectKey string) (output *s3.HeadObjectOutput, err error){
      s3Client := getS3Client()
      return s3Client.HeadObject(context.TODO(), &s3.HeadObjectInput{
        Bucket:               aws.String(bucketName),
        Key:                  aws.String(objectKey),
      })
    }
    
    func handleErrorOnS3HeadObjectAction(bucketName, objectKey string, err error) (hit bool){
      logUnableToHeadObjectFromS3Bucket(bucketName, objectKey, err)
      return err != nil
    }
    
    func logUnableToHeadObjectFromS3Bucket(bucketName string, objectKey string, err error) {
      if err != nil {
        log.Printf("Unable to head object {%s} from S3 bucket {%s}: { %v }", objectKey, bucketName, err)
      }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-12
      • 2023-03-14
      • 1970-01-01
      • 2015-07-27
      • 2020-06-14
      • 2013-09-06
      • 2020-11-06
      • 1970-01-01
      相关资源
      最近更新 更多