使用 boto 为 Amazon S3 密钥设置缓存标头时出现问题



我的Django项目使用django_compressor通过django-storages包通过boto将JavaScript和CSS文件存储在S3存储桶中。

与 django 存储相关的配置包括

if 'AWS_STORAGE_BUCKET_NAME' in os.environ:
    AWS_STORAGE_BUCKET_NAME = os.environ['AWS_STORAGE_BUCKET_NAME']
    AWS_HEADERS = {
        'Cache-Control': 'max-age=100000',
        'x-amz-acl': 'public-read',
    }
    AWS_QUERYSTRING_AUTH = False
    # This causes images to be stored in Amazon S3
    DEFAULT_FILE_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
    # This causes CSS and other static files to be served from S3 as well.
    STATICFILES_STORAGE = 'storages.backends.s3boto.S3BotoStorage'
    STATIC_ROOT = ''
    STATIC_URL = 'https://{0}.s3.amazonaws.com/'.format(AWS_STORAGE_BUCKET_NAME)
    # This causes conpressed CSS and JavaScript to also go in S3
    COMPRESS_STORAGE = STATICFILES_STORAGE
    COMPRESS_URL = STATIC_URL

这有效,除了当我访问 S3 管理控制台中的对象时,我看到 Cache-Control 标头中的等号已更改为 %3D ,如 max-age%3D100000 ,这停止了缓存的工作。

我写了一个小脚本来尝试按照以下思路解决此问题:

max_age = 30000000
cache_control = 'public, max-age={}'.format(max_age)
con = S3Connection(settings.AWS_ACCESS_KEY_ID, settings.AWS_SECRET_ACCESS_KEY)
bucket = con.get_bucket(settings.AWS_STORAGE_BUCKET_NAME)
for key in bucket.list():
    key.set_metadata('Cache-Control', cache_control)

但这不会更改 Amazon S3 管理控制台中显示的元数据。

(更新。S3 元数据的文档说

上传对象后,您无法修改对象元数据。修改对象元数据的唯一方法是复制对象并设置元数据。有关更多信息,请转到 Amazon Simple Storage Service API 参考中的 PUT 对象 - 复制。您可以使用 Amazon S3 管理控制台更新对象元数据,但在内部它会创建一个对象副本来替换现有对象以设置元数据。

所以也许我无法设置元数据并不奇怪。我假设get_metadata仅在首先创建数据时使用。

结束更新)

所以我的问题是,首先,我是否可以配置 django-storages 以便它首先正确创建 cache-control 标头,其次,set_metadata设置的元数据是否与使用 S3 管理控制台查看的元数据相同,如果不是后者是什么,我如何以编程方式设置它?

使用 ASCII 字符串作为值为我解决了这个问题。

AWS_HEADERS = {'Cache-Control': str('public, max-age=15552000')}

如果要在上传文件时添加缓存控制....

 headers = {
    'Cache-Control':'max-age=604800', # 60 x 60 x 24 x 7 = 1 week
    'Content-Type':content_type,
  }
  k = Key(self.get_bucket())
  k.key = filename
  k.set_contents_from_string(contents.getvalue(), headers)
  if self.public: k.make_public()

如果要向现有文件添加缓存控制...

for key in bucket.list():
  print key.name.encode('utf-8')
  metadata = key.metadata
  metadata['Cache-Control'] = 'max-age=604800' # 60 x 60 x 24 x 7 = 1 week
  key.copy(AWS_BUCKET, key, metadata=metadata, preserve_acl=True)

这在 boto 2.32 - 2.40 中进行了测试。

给未来访客的注意事项:使用 AWS_S3_OBJECT_PARAMETERS 而不是 boto3AWS_HEADERS

此外,CacheControl而不是Cache-Control。

所以最后它会是,

AWS_S3_OBJECT_PARAMETERS  = {'CacheControl' : str('max-age=525960')} #one year

来源: https://django-storages.readthedocs.io/en/latest/backends/amazon-S3.html

cache_control是键的属性,而不是元数据的一部分。

因此,要为存储桶中的所有对象设置缓存控制,您可以执行以下操作:

s3_conn = S3Connection(AWS_KEY, AWS_SECRET)
bucket = s3_conn.get_bucket(AWS_BUCKET_NAME)
bucket.make_public()
for key in bucket.list():
    key = bucket.get_key(key.name)
    key.cache_control = 'max-age=%d, public' % (3600 * 24 * 360 * 2)
    print key.name + ' ' +  key.cache_control

最新更新