有没有办法向客户端发出预签名的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'))
在明确提供标签的情况下上传时,这是令人满意的:
$ 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
但是,S3 在省略
-H 'x-amz-tagging: foo=bar'
时也会接受请求,即上传不带标签的对象。由于我无法控制客户,这……很糟糕。
我尝试先创建一个空对象并对其进行标记,然后向其发出预签名的 URL,但是
PUT
该对象会完全替换它,包括删除任何标记。
我尝试发出预签名的
POST
URL,但这似乎根本不支持 tagging
参数:
s3.generate_presigned_post('foo', 'bar', {'tagging': '<Tagging><TagSet><Tag><Key>Foo</Key><Value>Bar</Value></Tag></TagSet></Tagging>'})
$ 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>...
我只是想让客户端将文件直接上传到 S3,并确保在此过程中以某种方式标记它。有什么办法可以做到吗?
尝试以下代码:
fields = {
"tagging": "<Tagging><TagSet><Tag><Key>foo</Key><Value>bar</Value></Tag></TagSet></Tagging>"
"x-amz-meta-u1": "value1",
"x-amz-meta-u2": "value2"
}
conditions = [{key: value} for key, value in fields.items()]
presignedurl = s3_client.generate_presigned_post(
bucket_name, "YOUR_BUCKET_NAME",
Fields=copy.deepcopy(fields),
Conditions=copy.deepcopy(conditions)
)
Python代码:
fields = {
'tagging': '<Tagging><TagSet><Tag><Key>Foo</Key><Value>Bar</Value></Tag></TagSet></Tagging>',
}
conditions = [
{'tagging': '<Tagging><TagSet><Tag><Key>Foo</Key><Value>Bar</Value></Tag></TagSet></Tagging>'}
]
presigned_url = s3_client.generate_presigned_post(
Bucket="foo",
Key="file/key.json",
Fields=copy.deepcopy(fields),
Conditions=copy.deepcopy(conditions)
)
CURL 命令:
$ curl -v --form-string "tagging=<Tagging><TagSet><Tag><Key>Foo</Key><Value>Bar</Value></Tag></TagSet></Tagging>" \
-F key=file/key.json \
-F x-amz-algorithm=... \
-F x-amz-credential=... \
-F x-amz-date=... \
-F x-amz-security-token=... \
-F policy=...\
-F x-amz-signature=... \
-F [email protected] \
https://foo.s3.amazonaws.com/
在 CURL 命令中必须使用
--form-string
,否则 CURL 会将 =<
解释为读取文件!
还要确保
key.json
位于您当前的工作目录中,以便 CURL 使用预签名 URL 将文件上传到 S3。