web-dev-qa-db-ja.com

python boto3を使用してAWSS3の既存のオブジェクトのメタデータを更新するにはどうすればよいですか?

boto3のドキュメントでは、既存のS3オブジェクトのユーザーメタデータを更新する方法が明確に指定されていません。

11
arc000

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')
12
arc000

これは、リソースで copy_from()this answer など)の言及を使用して行うことができますが、クライアントの 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")
_

'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_は失敗します。 HTTP412エラーが発生します。

参照: boto3 issue 389

5
init_js

何かを追加するか、現在のメタデータ値を新しい値で更新することでメタデータを更新できます。これが私が使用しているコードの一部です。

import sys
import os 
import boto3
import pprint
from boto3 import client
from botocore.utils import fix_s3_Host
param_1= YOUR_ACCESS_KEY
param_2= YOUR_SECRETE_KEY
param_3= YOUR_END_POINT 
param_4= YOUR_BUCKET

#Create the S3 client
s3ressource = client(
    service_name='s3', 
    endpoint_url= param_3,
    aws_access_key_id= param_1,
    aws_secret_access_key=param_2,
    use_ssl=True,
    )
# Building a list of of object per bucket
def BuildObjectListPerBucket (variablebucket):
    global listofObjectstobeanalyzed
    listofObjectstobeanalyzed = []
    extensions = ['.jpg','.png']
    for key  in s3ressource.list_objects(Bucket=variablebucket)["Contents"]:
        #print (key ['Key'])
        onemoreObject=key['Key']
        if onemoreObject.endswith(Tuple(extensions)):
            listofObjectstobeanalyzed.append(onemoreObject)
    #print listofObjectstobeanalyzed
        else :
            s3ressource.delete_object(Bucket=variablebucket,Key=onemoreObject)          
    return listofObjectstobeanalyzed

# for a given existing object, create metadata
def createmetdata(bucketname,objectname):
    s3ressource.upload_file(objectname, bucketname, objectname, ExtraArgs={"Metadata": {"metadata1":"ImageName","metadata2":"ImagePROPERTIES" ,"metadata3":"ImageCREATIONDATE"}})

# for a given existing object, add new metadata
def ADDmetadata(bucketname,objectname):
    s3_object = s3ressource.get_object(Bucket=bucketname, Key=objectname)
    k = s3ressource.head_object(Bucket = bucketname, Key = objectname)
    m = k["Metadata"]
    m["new_metadata"] = "ImageNEWMETADATA"
    s3ressource.copy_object(Bucket = bucketname, Key = objectname, CopySource = bucketname + '/' + objectname, Metadata = m, MetadataDirective='REPLACE')

# for a given existing object, update  a metadata with new value
def CHANGEmetadata(bucketname,objectname):
    s3_object = s3ressource.get_object(Bucket=bucketname, Key=objectname)
    k = s3ressource.head_object(Bucket = bucketname, Key = objectname)
    m = k["Metadata"]
    m.update({'watson_visual_rec_dic':'ImageCREATIONDATEEEEEEEEEEEEEEEEEEEEEEEEEE'})
    s3ressource.copy_object(Bucket = bucketname, Key = objectname, CopySource = bucketname + '/' + objectname, Metadata = m, MetadataDirective='REPLACE')

def readmetadata (bucketname,objectname):
    ALLDATAOFOBJECT = s3ressource.get_object(Bucket=bucketname, Key=objectname)
    ALLDATAOFOBJECTMETADATA=ALLDATAOFOBJECT['Metadata']
    print ALLDATAOFOBJECTMETADATA



# create the list of object on a per bucket basis
BuildObjectListPerBucket (param_4)

# Call functions to see the results 
for objectitem in listofObjectstobeanalyzed:
    # CALL The function you want 
    readmetadata(param_4,objectitem)
    ADDmetadata(param_4,objectitem)
    readmetadata(param_4,objectitem)
    CHANGEmetadata(param_4,objectitem)
    readmetadata(param_4,objectitem)
0
MouIdri