在AWS S3上设置媒体文件访问

时间:2019-08-16 07:32:30

标签: django amazon-web-services amazon-s3 boto3 django-storage

我正在使用 boto3 django-storage 库来加载django项目的媒体文件。

storage_backends.py

 class PrivateMediaStorage(S3Boto3Storage):
    location = settings.AWS_STORAGE_LOCATION
    default_acl = 'private'
    file_overwrite = False
    custom_domain = False

class PublicStaticStorage(S3Boto3Storage):
    location = settings.AWS_PUBLIC_STATIC_LOCATION

settings.py

AWS_STORAGE_LOCATION = 'media/private'
AWS_LOCATION = 'static'
AWS_PUBLIC_STATIC_LOCATION = 'static/'
DEFAULT_FILE_STORAGE = 'path.to.PrivateMediaStorage'

models.py

class Documents(models.Model):
    """ uploaded documents"""

    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
    upload = models.FileField(storage=PrivateMediaStorage())
    filename = models.CharField(_('documents name'), max_length=255, blank=True, null=True)
    datafile = models.FileField()
    created = models.DateTimeField(auto_now_add=True)
    type = models.ForeignKey(Doctype, on_delete=models.CASCADE, blank=True)

文件加载效果很好。但是有一点我不理解,指向文件的链接看起来错误(它包含静态而不是媒体)。看起来像

https://myhost.s3.amazonaws.com/static/class-descriptions_1.csv

还有其他有关访问的信息。现在,我单击文件的链接,我收到一条消息

<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>4B8296F8F77491F5</RequestId>
<HostId>
CG96q+LGWcvsIK2YkuaE2wExL8/YTqH1PmjOSFGAqcgaKaTYnOet1QoItGJhW1Oj
</HostId>
</Error>

这对于未注册用户来说是正常的,但是如何允许在Django项目中注册的用户看到此文件?

2 个答案:

答案 0 :(得分:1)

您必须使用预签名的URL来实现此功能。如果存储桶是公共的,则所有用户都可以访问S3对象。如果要限制访问,则存储桶必须是私有的,并且需要为每个用户生成预签名的URL。

https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html

答案 1 :(得分:1)

要使媒体网址来自其他位置,您需要覆盖keydown设置:

DEFAULT_FILE_STORAGE

第二,如果您尚未在设置中定义DEFAULT_FILE_STORAGE = 'path.to.PrivateMediaStorage' ,则文件将使用从存储桶继承的ACL。可能已使用ACL private创建了存储区。这就是为什么无法访问文件的原因。

最后,关于访问错误。如果ACL是私有的,那么除了所有者之外,没有人可以访问它。因此,您需要更改目录的ACL。您可以使用s3tools。例如:

AWS_DEFAULT_ACL

  

这对于未注册用户来说是正常的,但是如何允许在Django项目中注册的用户看到此文件?

那不是ACL的工作方式。需要从S3存储桶中设置ACL访问权限。因此,如果ACL设置为s3cmd setacl --recursive s3://<bucket-name> --acl-public ,则不能禁止用户访问存储桶中的内容。

根据@vikyol的回答,有一种方法可以将预签名的URL发送给用户。

有关罐装ACL的详细信息,请检查亚马逊的documentation