在 AWS S3 上设置媒体文件访问
Setting up media file access on AWS S3
我正在使用 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)
文件加载正常。但是有一点我不明白,文件的 link 看起来不对(它包含静态而不是媒体)。看起来像
https://myhost.s3.amazonaws.com/static/class-descriptions_1.csv
以及关于访问的其他内容。现在我点击 link 到文件,我收到一条消息
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>4B8296F8F77491F5</RequestId>
<HostId>
CG96q+LGWcvsIK2YkuaE2wExL8/YTqH1PmjOSFGAqcgaKaTYnOet1QoItGJhW1Oj
</HostId>
</Error>
对于未注册的用户来说这是正常的,但是如何让在我的 Django 项目中注册的用户看到这个文件呢?
您必须使用预签名 URL 才能实现此功能。如果存储桶为 public,则所有用户都可以访问 S3 对象。如果您想限制访问,则存储桶必须是私有的,并且您需要为每个用户生成预签名的 URL。
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html
要使媒体 URL 来自不同的地方,您需要覆盖 DEFAULT_FILE_STORAGE
设置:
DEFAULT_FILE_STORAGE = 'path.to.PrivateMediaStorage'
其次,如果您没有在设置中定义AWS_DEFAULT_ACL
,那么文件将使用从存储桶继承的ACL。可能已使用 ACL private 创建了存储桶。这就是无法访问文件的原因。
最后,关于访问错误。如果 ACL 是私有的,那么除了所有者之外没有人可以访问它。所以你需要更改目录的 ACL。您可以为此使用 s3tools
。例如:
s3cmd setacl --recursive s3://<bucket-name> --acl-public
还有
This is normal for unregistered users, but how do I allow users registered in my Django project to see this file?
ACL 不是这样工作的。需要从 S3 存储桶设置 ACL 访问。因此,如果 ACL 设置为 public-read
,则不能禁止用户访问存储桶中的内容。
根据@vikyol 的回答,有一种方法可以将预签名的 URL 发送给用户。
有关 Canned ACL 的更多信息,请查看亚马逊的 documentation
。
我正在使用 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)
文件加载正常。但是有一点我不明白,文件的 link 看起来不对(它包含静态而不是媒体)。看起来像
https://myhost.s3.amazonaws.com/static/class-descriptions_1.csv
以及关于访问的其他内容。现在我点击 link 到文件,我收到一条消息
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>4B8296F8F77491F5</RequestId>
<HostId>
CG96q+LGWcvsIK2YkuaE2wExL8/YTqH1PmjOSFGAqcgaKaTYnOet1QoItGJhW1Oj
</HostId>
</Error>
对于未注册的用户来说这是正常的,但是如何让在我的 Django 项目中注册的用户看到这个文件呢?
您必须使用预签名 URL 才能实现此功能。如果存储桶为 public,则所有用户都可以访问 S3 对象。如果您想限制访问,则存储桶必须是私有的,并且您需要为每个用户生成预签名的 URL。
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html
要使媒体 URL 来自不同的地方,您需要覆盖 DEFAULT_FILE_STORAGE
设置:
DEFAULT_FILE_STORAGE = 'path.to.PrivateMediaStorage'
其次,如果您没有在设置中定义AWS_DEFAULT_ACL
,那么文件将使用从存储桶继承的ACL。可能已使用 ACL private 创建了存储桶。这就是无法访问文件的原因。
最后,关于访问错误。如果 ACL 是私有的,那么除了所有者之外没有人可以访问它。所以你需要更改目录的 ACL。您可以为此使用 s3tools
。例如:
s3cmd setacl --recursive s3://<bucket-name> --acl-public
还有
This is normal for unregistered users, but how do I allow users registered in my Django project to see this file?
ACL 不是这样工作的。需要从 S3 存储桶设置 ACL 访问。因此,如果 ACL 设置为 public-read
,则不能禁止用户访问存储桶中的内容。
根据@vikyol 的回答,有一种方法可以将预签名的 URL 发送给用户。
有关 Canned ACL 的更多信息,请查看亚马逊的 documentation
。