有没有办法使用预先签名的URL上传和强制标记?

dec*_*eze 8 amazon-s3 aws-sdk

有没有办法向客户端发送预先签名的URL以将文件上传到S3,并确保上传的文件有某些标签?以此处使用Python SDK为例,可根据需要生成URL:

s3.generate_presigned_url('put_object', 
                          ExpiresIn=3600,
                          Params=dict(Bucket='foo', 
                                      Key='bar', 
                                      ContentType='text/plain', 
                                      Tagging='foo=bar'))
Run Code Online (Sandbox Code Playgroud)

在明确提供标签时上传时这是令人满意的:

$ curl 'https://foo.s3.amazonaws.com/bar?AWSAccessKeyId=...&Signature=...&content-type=text%2Fplain&x-amz-tagging=foo%3Dbar&Expires=1538404508' \
  -X PUT
  -H 'Content-Type: text/plain' \
  -H 'x-amz-tagging: foo=bar' \
  --data-binary foobar
Run Code Online (Sandbox Code Playgroud)

但是,S3在省略时也接受请求-H 'x-amz-tagging: foo=bar',该请求在没有标签的情况下上传对象.由于我无法控制客户端,所以......糟糕.

我已经尝试先创建一个空对象并对其进行标记,然后向其发出预先指定的URL,但是PUT该对象将完全替换它,包括删除任何标记.

我尝试过发布预先签名的POSTURL,但似乎根本不支持该tagging参数:

s3.generate_presigned_post('foo', 'bar', {'tagging': '<Tagging><TagSet><Tag><Key>Foo</Key><Value>Bar</Value></Tag></TagSet></Tagging>'})
Run Code Online (Sandbox Code Playgroud)
$ curl https://foo.s3.amazonaws.com/ \
  -F key=bar \
  -F 'tagging=<Tagging><TagSet><Tag><Key>Foo</Key><Value>Bar</Value></Tag></TagSet></Tagging>'
  -F AWSAccessKeyId=... \
  -F policy=... \
  -F signature=... \
  -F file=@/tmp/foo

<Error><Code>AccessDenied</Code><Message>Invalid according to Policy:
Extra input fields: tagging</Message>...
Run Code Online (Sandbox Code Playgroud)

我只是想让客户端直接将文件上传到S3,并确保它在流程中以某种方式标记.有办法吗?

Rez*_*avi 7

尝试以下代码:

fields = {
    "x-amz-meta-u1": "value1",
    "x-amz-meta-u2": "value2"
}
conditions = [
    {"x-amz-meta-u1": "value1"},
    {"x-amz-meta-u2": "value2"}
]


presignedurl = s3_client.generate_presigned_post(
    bucket_name, "YOUR_BUCKET_NAME",
    Fields=copy.deepcopy(fields),
    Conditions=copy.deepcopy(conditions)
)
Run Code Online (Sandbox Code Playgroud)