How to change metadata on an object in Amazon S3

Question:

If you have already uploaded an object to an Amazon S3 bucket, how do you change the metadata using the API? It is possible to do this in the AWS Management Console, but it is not clear how it could be done programmatically. Specifically, I’m using the boto API in Python and from reading the source it is clear that using key.set_metadata only works before the object is created as it just effects a local dictionary.

Asked By: natevw

||

Answers:

It appears you need to overwrite the object with itself, using a “PUT Object (Copy)” with an x-amz-metadata-directive: REPLACE header in addition to the metadata. In boto, this can be done like this:

k = k.copy(k.bucket.name, k.name, {'myKey':'myValue'}, preserve_acl=True)

Note that any metadata you do not include in the old dictionary will be dropped. So to preserve old attributes you’ll need to do something like:

k.metadata.update({'myKey':'myValue'})
k2 = k.copy(k.bucket.name, k.name, k.metadata, preserve_acl=True)
k2.metadata = k.metadata    # boto gives back an object without *any* metadata
k = k2;

I almost missed this solution, which is hinted at in the intro to an incorrectly-titled question that’s actually about a different problem than this question: Change Content-Disposition of existing S3 object

Answered By: natevw

You can change the metadata without re-uloading the object by using the copy command. See this question: Is it possible to change headers on an S3 object without downloading the entire object?

Answered By: John Bachir

In order to set metadata on S3 files,just don’t provide target location as only source information is enough to set metadata.

final ObjectMetadata metadata = new ObjectMetadata();
metadata.addUserMetadata(metadataKey, value);
final CopyObjectRequest request = new CopyObjectRequest(bucketName, keyName, bucketName, keyName)
  .withSourceBucketName(bucketName)
  .withSourceKey(keyName)
  .withNewObjectMetadata(metadata);

s3.copyObject(request);`
Answered By: kartik

For the first answer it’s a good idea to include the original content type in the metadata, for example:

key.set_metadata('Content-Type', key.content_type) 
Answered By: Ted

If you want your metadata stored remotely use set_remote_metadata

Example:
key.set_remote_metadata({'to_be': 'added'}, ['key', 'to', 'delete'], {True/False})

Implementation is here:
https://github.com/boto/boto/blob/66b360449812d857b4ec6a9834a752825e1e7603/boto/s3/key.py#L1875

Answered By: eddd

In Java, You can copy object to the same location.
Here metadata will not copy while copying an Object.
You have to get metadata of original and set to copy request.
This method is more recommended to insert or update metadata of an Amazon S3 object

ObjectMetadata metadata = amazonS3Client.getObjectMetadata(bucketName, fileKey);
ObjectMetadata metadataCopy = new ObjectMetadata();
metadataCopy.addUserMetadata("yourKey", "updateValue");
metadataCopy.addUserMetadata("otherKey", "newValue");
metadataCopy.addUserMetadata("existingKey", metadata.getUserMetaDataOf("existingValue"));

CopyObjectRequest request = new CopyObjectRequest(bucketName, fileKey, bucketName, fileKey)
      .withSourceBucketName(bucketName)
      .withSourceKey(fileKey)
      .withNewObjectMetadata(metadataCopy);

amazonS3Client.copyObject(request);
Answered By: Jefin Stephan

here is the code that worked for me. I’m using aws-java-sdk-s3 version 1.10.15

ObjectMetadata metadata = new ObjectMetadata();
metadata.setContentType(fileExtension.getMediaType());

s3Client.putObject(new PutObjectRequest(bucketName, keyName, tempFile)
                    .withMetadata(metadata));
Answered By: Rogelio Blanco
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.