leo
leo

Reputation: 8541

How do I set the Content-Type of an existing S3 key with boto3?

I want to update the Content-Type of an existing object in a S3 bucket, using boto3, but how do I do that, without having to re-upload the file?

    file_object = s3.Object(bucket_name, key)
    print file_object.content_type
    # binary/octet-stream
    file_object.content_type = 'application/pdf'
    # AttributeError: can't set attribute

Is there a method for this I have missed in boto3?

Related questions:

Upvotes: 14

Views: 13026

Answers (3)

Abu Tahir
Abu Tahir

Reputation: 11

You can use upload_file function from boto3 and use ExtraArgs param to specify the content type, this will overwrite the existing file with the content type, check out this reference

check this below example:

import boto3
import os

client = boto3.client("s3")

temp_file_path = "<path_of_your_file>"
client.upload_file(temp_ticket_path, <BUCKET_NAME>, temp_file_path, ExtraArgs={'ContentType': 'application/pdf'})

Upvotes: 0

cannereau
cannereau

Reputation: 61

In addition to @leo's answer, be careful if you have custom metadata on your object. To avoid side effects, I propose adding Metadata=object.metadata in the leo's code otherwise you could lose previous custom metadata:

s3 = boto3.resource("s3")
object = s3.Object(bucket_name, key)
object.copy_from(
          CopySource={'Bucket': bucket_name, 'Key': key},
          Metadata=object.metadata,
          MetadataDirective="REPLACE",
          ContentType="application/pdf"
)

Upvotes: 4

leo
leo

Reputation: 8541

There doesn't seem to exist any method for this in boto3, but you can copy the file to overwrite itself.

To do this using the AWS low level API through boto3, do like this:

s3 = boto3.resource('s3')
api_client = s3.meta.client
response = api_client.copy_object(Bucket=bucket_name,
                                  Key=key,
                                  ContentType="application/pdf",
                                  MetadataDirective="REPLACE",
                                  CopySource=bucket_name + "/" + key)

The MetadataDirective="REPLACE" turns out to be required for S3 to overwrite the file, otherwise you will get an error message saying This copy request is illegal because it is trying to copy an object to itself without changing the object's metadata, storage class, website redirect location or encryption attributes. .

Or you can use copy_from, as pointed out by Jordon Phillips in the comments:

s3 = boto3.resource("s3")
object = s3.Object(bucket_name, key)
object.copy_from(CopySource={'Bucket': bucket_name,
                             'Key': key},
                 MetadataDirective="REPLACE",
                 ContentType="application/pdf")

Upvotes: 18

Related Questions