无法在S3中设置文件内容类型

9
你如何通过Python的boto模块在启用Web托管的S3帐户中设置文件的内容类型?
我正在执行以下操作:
from boto.s3.connection import S3Connection
from boto.s3.key import Key
from boto.cloudfront import CloudFrontConnection

conn = S3Connection(access_key_id, secret_access_key)
bucket = conn.create_bucket('mybucket')
b = conn.get_bucket(bucket)
b.set_acl('public-read')

fn = 'index.html'
template = '<html>blah</html>'
k = Key(b)
k.key = fn
k.set_contents_from_string(template)
k.set_acl('public-read')
k.set_metadata('Content-Type', 'text/html')

然而,当我从http://mybucket.s3-website-us-east-1.amazonaws.com/index.html访问它时,我的浏览器提示我下载该文件,而不是像普通网页一样提供服务。
在S3管理控制台中查看元数据时,显示Content-Type实际上被设置为“application/octet-stream”。如果我在控制台中手动更改它,我就可以正常访问该页面,但是如果我再次运行我的脚本,则会将其重置回错误的内容类型。
我做错了什么?

我不是完全确定,但如果我记得正确的话,你操作的顺序非常重要。尝试重新排序您的关键操作 - 例如,在设置内容之前设置Content-Type元数据。 - lanzz
4个回答

17

set_metadata方法主要用于设置S3对象上的用户元数据。许多标准HTTP元数据字段都有一级属性来表示它们,例如content_type。此外,在将对象发送到S3之前,您需要设置元数据。以下代码应该可以实现:

set_metadata方法主要用于设置S3对象上的用户元数据。许多标准HTTP元数据字段都有一级属性来表示它们,例如content_type。此外,在将对象发送到S3之前,您需要设置元数据。以下代码应该可以实现:

import boto

conn = boto.connect_s3()
bucket = conn.get_bucket('mybucket')  # Assumes bucket already exists
key = bucket.new_key('mykey')
key.content_type = 'text/html'
key.set_contents_from_string(mystring, policy='public-read')

请注意,您可以在将对象写入S3时设置预设的ACL策略,这样可以避免另外进行API调用。


3

对于需要一句话概括的人,

import boto3
s3 = boto3.resource('s3')

s3.Bucket('bucketName').put_object(Key='keyName', Body='content or fileData', ContentType='contentType', ACL='check below')

支持的ACL值:

'private'|'public-read'|'public-read-write'|'authenticated-read'|'aws-exec-read'|'bucket-owner-read'|'bucket-owner-full-control'

put_object支持的参数可以在这里找到,https://boto3.readthedocs.io/en/latest/reference/services/s3.html#S3.Client.put_object


0

我无法使上述解决方案实际持久化我的元数据更改。

可能是因为我正在使用文件,并且它正在使用mimetype重置内容类型?此外,我正在上传用于HLS编码的m3u8和ts文件,这也可能会干扰。

无论如何,以下是对我有效的方法。

import boto
conn = boto.connect_s3()
bucket = conn.get_bucket('mybucket')
key_m3u8 = Key(bucket_handle)
key_m3u8.key = s3folder+"/"+s3keyname
key_m3u8.metadata = {"Content-Type":"application/x-mpegURL","Cache-Control":"public,max-age=8"}                             
key_m3u8.set_contents_from_filename("path_to_my_file", policy="public-read")

bucket_handle是什么? - Boswell Gathu
这只是一个包含 S3 存储桶名称的字符串。 - carterh062

0

如果您使用 AWS S3 Bitbucket Pipelines Python,请添加参数 content_type

s3_upload.py

def upload_to_s3(bucket, artefact, bucket_key, content_type):
...

def main():
...
    parser.add_argument("content_type", help="Content Type File")
...

if not upload_to_s3(args.bucket, args.artefact, args.bucket_key, args.content_type):

然后按照以下方式修改 bitbucket-pipelines.yml

...
- python s3_upload.py bucket_name file key content_type 
...

content_type 参数可以是以下之一:MIME 类型(IANA 媒体类型)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接