如何使用 boto3 设置现有 S3 密钥的内容类型?

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

我想使用 boto3 更新 S3 存储桶中现有对象的内容类型,但我该怎么做,而不必重新上传文件?

    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

有没有我在 boto3 中遗漏的方法?

相关问题:

boto3好像没有这个方法,不过你可以复制文件覆盖自己。

要通过 boto3 使用 AWS 低级别 API 执行此操作,请执行以下操作:

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)

事实证明,MetadataDirective="REPLACE" 是 S3 覆盖文件所必需的,否则您将收到一条错误消息,指出 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. .

或者您可以使用 copy_from,正如 Jordon Phillips 在评论中指出的那样:

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

除了@leo 的回答之外,如果您的对象上有自定义元数据,请小心。 为了避免副作用,我建议在 leo 的代码中添加 Metadata=object.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"
)

您可以使用 boto3 中的 upload_file 函数并使用 ExtraArgs 参数指定内容类型,这将使​​用该内容类型覆盖现有文件,查看此 reference

检查以下示例:

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