【问题标题】:Trouble setting cache-cotrol header for Amazon S3 key using boto使用 boto 为 Amazon S3 键设置缓存控制标头时遇到问题
【发布时间】:2013-10-23 11:01:43
【问题描述】:

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

django-storages 相关配置包括

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 管理控制台中显示的元数据。

(更新The documentation for S3 metadata

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

所以也许我不能设置元数据也就不足为奇了。我假设get_metadata 仅在首先创建数据时使用。

结束更新)

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

【问题讨论】:

    标签: django amazon-s3 boto


    【解决方案1】:

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

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

    【讨论】:

    • 你能添加更完整的例子吗?我现在正在猜测将您的解决方案粘贴到哪里。
    • 有关我无法正确格式化的更完整示例...` headers = { 'Cache-Control':'max-age=604800', # 60 x 60 x 24 x 7 = 1 周 '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() ` 为我工作。请参阅下面的完整答案...
    • 使用 python 2.7 为我工作,不清楚这是如何避免 URL 编码器但很好的发现。
    • '-' 现已移除,仅驼色外壳。 'CacheControl', 'ContentType'
    【解决方案2】:

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

     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 中测试的。

    【讨论】:

      【解决方案3】:

      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
      

      【讨论】:

      • 这行不通。正如更新后的问题所说,设置新缓存控制标头的唯一方法是“移动”文件。
      猜你喜欢
      • 2014-08-18
      • 2012-12-12
      • 2013-10-25
      • 2023-04-03
      • 2013-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-14
      相关资源
      最近更新 更多