我使用django、celery和boto来实现。我设置了一个celery任务,从我的一个视图中获取一些信息,然后进行处理,并将新文件发布到S3上。我能够成功地从S3获取原始文件,进行操作,并将其重新发布到S3上。唯一不起作用的是更改该文件的权限。因此,当您转到查看页面时,除了无法访问该文件以外,其他都正常运行,报403(禁止)错误。
如果我自己进入S3并将该文件的权限更改为每个人都可以读取,那么它就可以工作。在继续之前,我在我的任务中使用的几乎可行的代码是:
name = 'filename.blah'
conn = boto.connect_s3()
b = conn.get_bucket(settings.AWS_STORAGE_BUCKET_NAME)
grab_from_S3(name,b) # grab file from S3
out_name = conv(name)
send_to_S3(out_name,b)
这里的函数包括:
def grab_from_S3(file,bucket):
k = Key(bucket)
k.key = file
k.get_contents_to_filename(file)
def send_to_S3(file,bucket):
k = Key(bucket)
k.key = file
k.set_contents_from_filename(file)
k.set_acl('public-read')
conv(name)函数只是进行一些转换操作。所以这个代码几乎都能正常工作,除了文件的权限不是'public-read'。我假设所有的AWS凭证和存储桶名称都已正确从环境中导入,因为它能够将文件推送到S3并从S3中拉取文件。
令人困惑的是,当我从EC2服务器上的venv或最初安装在其中的python中打开python环境,并运行上面显示的所有命令时,它确实可以正常工作。我可以轻松更改权限。当任务运行时,在celery日志中不会抛出任何错误,因此我认为任务实际上没有遇到错误。它只是没有按照预期更改。
我尝试过的事情:
- 我尝试使用其他版本的权限函数,例如
k.set_contents_from_filename(file,policy='public-read')
、k.make_public()
或b.set_acl('public-read',out_name)
,但这些都没有起作用。 - 我将存储桶的权限更改为允许每个人更改权限,但仍然不起作用。
我尝试将存储桶策略更改为以下内容,但没有效果:
{ "Version": "2008-10-17", "Id": "whatever", "Statement": [ { "Sid": "whatever", "Effect": "Allow", "Principal": { "AWS": "*" }, "Action": [ "s3:PutObjectAcl", "s3:PutObject"], "Resource": [ "arn:aws:s3:::bucket_name", "arn:aws:s3:::bucket_name/*" ] } ] }
最后,我真的很困惑,因为我似乎可以在同一EC2实例上的python环境中完成所有这些操作,但不能在运行在该实例上的代码中完成。我已经搜索了很长时间,没有找到任何有效的建议。另一个可能有用的信息(但根据问题可能不相关)是,如果我尝试通过执行类似于上面的命令来连接S3,则会返回错误:
"No handler was ready to authenticate. 1 handlers were checked. ['HmacAuthV1Handler'] Check your credentials"
尽管在任务中运行这些命令时它是有效的(我认为它是错误的访问密钥或秘密访问密钥之类的问题,但它与其他所有内容都有效)。我认为我在需要的boto库的python代码中进行了正确的导入。
我最近刚刚设置了这个实例,所以它几乎拥有最新版本的boto、celery、django等。我可能忘记了一些东西。如果您需要更多信息来回答问题,请告诉我。我真的不知道发生了什么。
非常感谢您的帮助。