如何使用python boto3更新AWS S3中现有对象的元数据?

arc*_*000 10 python amazon-s3 amazon-web-services boto3

boto3文档没有明确说明如何更新已存在的S3对象的用户元数据.

arc*_*000 11

可以使用copy_from()方法来完成-

import boto3

s3 = boto3.resource('s3')
s3_object = s3.Object('bucket-name', 'key')
s3_object.metadata.update({'id':'value'})
s3_object.copy_from(CopySource={'Bucket':'bucket-name', 'Key':'key'}, Metadata=s3_object.metadata, MetadataDirective='REPLACE')
Run Code Online (Sandbox Code Playgroud)

  • @ChinsKuriakose AWS 文档说“您可以在上传对象元数据时设置对象元数据。上传对象后,您无法修改对象元数据。”(https://docs.aws.amazon.com/AmazonS3/latest/dev /UsingMetadata.html)。因此,元数据基本上是不可变的,因此在更新对象时实际上会复制对象。 (2认同)
  • 我们可以更新系统定义的对象吗?尝试了该解决方案,但它按照用户定义进行。如果您提供任何帮助,那将非常有帮助。 (2认同)

ini*_*_js 9

您可以使用copy_from()资源(如此答案)提及来执行此操作,但您也可以使用客户端copy_object()并指定相同的源和目标。这些方法是等效的,并且在下面调用相同的代码。

import boto3
s3 = boto3.client("s3")
src_key = "my-key"
src_bucket = "my-bucket"
s3.copy_object(Key=src_key, Bucket=src_bucket,
               CopySource={"Bucket": src_bucket, "Key": src_key},
               Metadata={"my_new_key": "my_new_val"},
               MetadataDirective="REPLACE")
Run Code Online (Sandbox Code Playgroud)

“REPLACE”值指定请求中传递的元数据应完全覆盖源元数据。如果您只想添加新的键值或仅删除某些键,则必须首先读取原始数据,对其进行编辑并调用更新。

要仅正确替换元数据的一个子集

  1. 使用 检索原始元数据head_object(Key=src_key, Bucket=src_bucket)。还要注意响应中的 Etag
  2. 在本地对元数据进行所需的更改。
  3. copy_object如上调用以上传新的元数据,但传入CopySourceIfMatch=original_etag请求以确保远程对象在覆盖它之前具有您期望的元数据。original_etag是您在第 1 步中得到的那个。如果元数据(或数据本身)自head_object被调用(例如,被另一个同时运行的程序)更改后,copy_object将失败并显示 HTTP 412 错误。

参考:boto3 问题 389


Adi*_*Kar 8

与此答案类似,但保留现有元数据,同时仅修改需要的内容。根据系统定义的元数据,我在此示例中仅保留了 ContentType 和 ContentDisposition。其他系统定义的元数据也可以类似地保存。

import boto3

s3 = boto3.client('s3')
response = s3.head_object(Bucket=bucket_name, Key=object_name)
response['Metadata']['new_meta_key'] = "new_value"
response['Metadata']['existing_meta_key'] = "new_value"
result = s3.copy_object(Bucket=bucket_name, Key=object_name,
                        CopySource={'Bucket': bucket_name,
                                    'Key': object_name},
                        Metadata=response['Metadata'],
                        MetadataDirective='REPLACE', TaggingDirective='COPY',
                        ContentDisposition=response['ContentDisposition'],
                        ContentType=response['ContentType'])
Run Code Online (Sandbox Code Playgroud)