Leem.fin
Leem.fin

Reputation: 42582

update metadata in s3

I use Amazon boto v2.38 to write python script to access my S3 bucket.

I want to update a file in my bucket (I know it is called "key" in S3). The path is MyBucket/myfile/demo.txt . Besides, I want to also update its metadata named "name". Here is the code I tried:

# connect to key
conn = boto.connect_s3()
bucket = conn.get_bucket("MyBucket")

my_key = Key(bucket)
my_key.key = "myfile/demo.txt"

# if key exists, then update the file & its metadata
if my_key.exists():
   new_meta_data = {"name": "xyz"}
   # update metadata
   my_key.copy("MyBucket", my_key.name, new_meta_data, preserve_acl=True)
   # update file content in S3 by using the local file demo.txt
   my_key.set_contents_from_filename("demo.txt")

However, it doesn't work... I don't see metadata get updated. Why?

Upvotes: 1

Views: 5573

Answers (3)

MouIdri
MouIdri

Reputation: 1390

Using Boto3, be careful if using "put_object" with metadata, this will change your actual metadatas, if you want to to create Object with metadatas, then add metadata or update an existing metadata, use the below :

import sys
import os 
import boto3
from boto3 import client

param_1= sys.argv[1] 
param_2= sys.argv[2] 
param_3= sys.argv[3]  
param_4= sys.argv[4]
param_5= sys.argv[5]

objectNMAE='THIEF.jpg'

s3ressource = client(
    service_name='s3', 
    endpoint_url= param_3,
    aws_access_key_id= param_1,
    aws_secret_access_key=param_2,
    use_ssl=True,
    )

def createmetdata(bucketname,objectname):
    s3ressource.upload_file(objectname, bucketname, objectname, ExtraArgs={"Metadata": {"metadata1":"ImageName","metadata2":"ImagePROPERTIES" ,"metadata3":"ImageCREATIONDATE"}})

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

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({'metadata3':'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

createmetdata(param_4,objectNMAE)
readmetadata(param_4,objectNMAE)
ADDmetadata(param_4,objectNMAE)
readmetadata(param_4,objectNMAE)
CHANGEmetadata(param_4,objectNMAE)
readmetadata(param_4,objectNMAE)

Upvotes: 0

mhawke
mhawke

Reputation: 87054

You can just update the key's local metadata and then perform the file update:

import boto

conn = boto.connect_s3()
bucket = conn.get_bucket("MyBucket")
key = bucket.get_key('myfile/demo.txt')
key.set_metadata('name', 'xyz')
key.set_contents_from_filename('demo.txt')

Now name should appear as metadata within S3. Note, however, that the ACL might change when you do this.

It can also be done with key.set_remote_metadata(). This does not require that you update the key's content (but you can if you want):

conn = boto.connect_s3()
bucket = conn.get_bucket('MyBucket')
key = bucket.get_key('myfile/demo.txt')
key.set_remote_metadata({'name': 'xyz'}, {}, True)

Upvotes: 5

jruizaranguren
jruizaranguren

Reputation: 13597

The following code change the key metadata in boto3:

import boto3 as aws

s3 = aws.resource('s3')
obj = s3.Bucket('MyBucket').Object('objectKey')
obj.put(Metadata={'name':'newName'}

According to the docs, set_metadata must be used. I have tested it and the foloowing code works with boto2 and changes the meatadata:

import boto as aws

cx=aws.connect_s3()
bucket=cx.get_bucket('MyBucket')
obj=bucket.get_key('objectKey')
obj.set_metadata('name', 'newName')

Upvotes: 0

Related Questions