问题
Im using boto3 and django-storage libraries for apload media files of my django project.
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)
File loading works well. But there is a point I don't understand, and the link to the file looks wrong (it contains static instead of media). Looks like
https://myhost.s3.amazonaws.com/static/class-descriptions_1.csv
And else about access. Now that I click on the link to the file, I get a message
<Error>
<Code>AccessDenied</Code>
<Message>Access Denied</Message>
<RequestId>4B8296F8F77491F5</RequestId>
<HostId>
CG96q+LGWcvsIK2YkuaE2wExL8/YTqH1PmjOSFGAqcgaKaTYnOet1QoItGJhW1Oj
</HostId>
</Error>
This is normal for unregistered users, but how do I allow users registered in my Django project to see this file?
回答1:
You have to use pre-signed URLs to implement this functionality. All users can access S3 objects if the bucket is public. If you want to restrict access, then the bucket has to be private and you need to generate pre-signed URLs per user.
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/s3-presigned-urls.html
回答2:
To make the media urls come from a different place, you need to override DEFAULT_FILE_STORAGE
settings:
DEFAULT_FILE_STORAGE = 'path.to.PrivateMediaStorage'
Secondly, if you haven't defined AWS_DEFAULT_ACL
in settings, then the files will use ACL inherited from the bucket. Probably bucket has been created with ACL private. Thats why the files can't be accessed.
Finally, regarding the access error. If the ACL is private, then no one can access it apart from the owner. So you need to change the ACL of the directories. You can use s3tools for that. For example:
s3cmd setacl --recursive s3://<bucket-name> --acl-public
Also
This is normal for unregistered users, but how do I allow users registered in my Django project to see this file?
Thats not how ACL works. ACL access needs to be set from S3 bucket. So you can't forbid user from accessing the contents from bucket if ACL is set to public-read
.
As per @vikyol's answer, there is a way to send pre-signed URLs to user.
For more information on Canned ACL, please check the documentation by amazon.
来源:https://stackoverflow.com/questions/57520553/setting-up-media-file-access-on-aws-s3