我有一个django项目,在s3-boto上使用django-storage。
问题是位于S3上的每个文件都无法缓存,因为每个调用都更改了URL。
这是django-storage生成的两个调用:
https://my.s3.amazonaws.com/cache/user_6/profile_pic/profile_profile_picture_thumbnail.jpg?Signature=HlVSayUIJj6dMyk%2F4KBtFlz0uJs%3D&Expires=1364418058&AWSAccessKeyId=[awsaccesskey]
https://my.s3.amazonaws.com/cache/user_6/profile_pic/profile_profile_picture_thumbnail.jpg?Signature=xh2VxKys0pkq7yHpbJmH000wkwg%3D&Expires=1364418110&AWSAccessKeyId=[awsaccesskey]
正如您所看到的,签名是不同的。我能做什么,不会破坏我的浏览器缓存?
答案 0 :(得分:9)
在您的设置中,只需添加以下内容:
AWS_QUERYSTRING_AUTH = False
这将确保生成文件的URL而不使用额外的参数。您的网址如下:
https://my.s3.amazonaws.com/cache/user_6/profile_pic/profile_profile_picture_thumbnail.jpg
答案 1 :(得分:2)
您最好的选择是继承Boto S3存储后端并覆盖url方法。
from django.conf import settings
from storages.backends.s3boto import S3BotoStorage
class S3Storage(S3BotoStorage):
def url(self, name):
name = self._clean_name(name)
return '{0}{1}'.format(settings.MEDIA_URL, name)
MEDIA_URL = 'https://my.s3.amazonaws.com/'
DEFAULT_FILE_STORAGE = 'project.storage.S3Storage'
AWS_ACCESS_KEY_ID = '*******'
AWS_SECRET_ACCESS_KEY = '********'
AWS_STORAGE_BUCKET_NAME = 'your-bucket'
只需确保您的图片可公开阅读。
答案 2 :(得分:0)
保护一些文件存储空间
您的大多数媒体上传 - 例如用户头像 - 您想要公开。但是,如果您有一些需要身份验证的媒体才能访问它 - 比如只有成员可以访问的PDF简历 - 那么您不希望S3BotoStorage的公共读取的默认S3 ACL。这里我们没有子类,因为我们可以传入一个实例而不是引用一个类。
首先删除设置中所有文件字段的保护并添加缓存控件
AWS_HEADERS = {
'Cache-Control': 'max-age=86400',
}
# By default don't protect s3 urls and handle that in the model
AWS_QUERYSTRING_AUTH = False
然后将您需要保护的文件字段设置为使用自定义受保护路径
from django.db import models
import storages.backends.s3boto
protected_storage = storages.backends.s3boto.S3BotoStorage(
acl='private',
querystring_auth=True,
querystring_expire=600, # 10 minutes, try to ensure people won't/can't share
)
class Profile(models.Model):
resume = models.FileField(
null=True,
blank=True,
help_text='PDF resume accessible only to members',
storage=protected_storage,
)
但是当你在开发中时,你还需要使用正常的存储空间,并且你通常使用本地存储,所以这就是我亲自去做的事情
if settings.DEFAULT_FILE_STORAGE == 'django.core.files.storage.FileSystemStorage':
protected_storage = FileSystemStorage()
logger.debug('Using FileSystemStorage for resumes files')
else:
protected_storage = S3BotoStorage(
acl='private',
querystring_auth=True,
querystring_expire=86400, # 24Hrs, expiration try to ensure people won't/can't share after 24Hrs
)
logger.debug('Using protected S3BotoStorage for resumes files')
参考:https://tartarus.org/james/diary/2013/07/18/fun-with-django-storage-backends
答案 3 :(得分:0)
当AWS_QUERYSTRING_AUTH = True
(这是默认设置)时,django会在每次获取网址时生成临时网址 。
将AWS_QUERYSTRING_AUTH = False
添加到您的settings.py
临时网址的有效期为AWS_QUERYSTRING_EXPIRE
秒(默认为3600)。所以我们可以缓存这个临时网址(只要我们不缓存它的时间超过它的有效时间)。这样 - 我们可以为后续页面请求返回相同的URL,允许客户端浏览器从其缓存中获取。
<强> settings.py 强>
# We subclass the default storage engine to add some caching
DEFAULT_FILE_STORAGE = 'project.storage.CachedS3Boto3Storage'
<强>项目/ storage.py 强>
import hashlib
from django.conf import settings
from django.core.cache import cache
from storages.backends.s3boto3 import S3Boto3Storage
class CachedS3Boto3Storage(S3Boto3Storage):
""" adds caching for temporary urls """
def url(self, name):
# Add a prefix to avoid conflicts with any other apps
key = hashlib.md5("CachedS3Boto3Storage_%s" % name).hexdigest()
result = cache.get(key)
if result:
return result
# No cached value exists, follow the usual logic
result = super(CachedS3Boto3Storage, self).url(name)
# Cache the result for 3/4 of the temp_url's lifetime.
try:
timeout = settings.AWS_QUERYSTRING_EXPIRE
except:
timeout = 3600
timeout = int(timeout*.75)
cache.set(key, result, timeout)
return result
答案 4 :(得分:0)
如果您关心使用签名的URL,但仍要缓存它们直到它们过期,则只需使用django内置的caching:
from django.core.cache import cache
class MyModel(models.Model):
#using django-storages with AWS_QUERYSTRING_AUTH=True
media = models.FileField()
@property
def url(self):
"""
Return signed url, re-using cached value if not expired.
"""
#Refresh url if within n seconds of expiry to give clients
#time to retrieve content from bucket.
#Make sure AWS_QUERYSTRING_EXPIRE is sufficiently larger than n
n = 30
time_to_expiry = settings.AWS_QUERYSTRING_EXPIRE - n
#Create a unique key for this instance's url in the cache
key = '{0}{1}'.format(self.__class__.__name__, self.pk)
url = cache.get(key)
if not url:
url = self.media.url #refresh url via django-storages
cache.set(key, url, time_to_expiry)
return url
答案 5 :(得分:0)
在settings.py文件中添加此行将启用图像文件的缓存。
AWS_S3_OBJECT_PARAMETERS = {
'CacheControl': 'max-age=86400',
}