【问题标题】:Django collectstatic result in S3ResponseError: 301 Moved PermanentlyDjango collectstatic 结果导致 S3ResponseError: 301 Moved Permanently
【发布时间】:2016-07-12 06:15:06
【问题描述】:

我正在运行一个将所有静态和媒体文件添加到 Amazon S3 的 Django 项目。我正在使用我过去多次使用的 settings.py 配置,它适用于多个其他项目(发布在下面)。

当我在自己的本地主机上使用相同的 settings.py 文件时。我可以很好地运行python manage.py collectstatic --noinput,它会将所有静态文件上传到 Amazon S3。但是,当我将项目放在 Elastic Beanstalk 应用程序服务器上并使用相同的设置运行相同的命令时,我得到了S3ResponseError: 301 Moved Permanently

我的设置是:

AWS_STORAGE_BUCKET_NAME = 's3.cupcard.com'
AWS_S3_CUSTOM_DOMAIN = AWS_STORAGE_BUCKET_NAME
AWS_S3_CALLING_FORMAT = 'boto.s3.connection.OrdinaryCallingFormat'
AWS_S3_SECURE_URLS = False
AWS_S3_URL_PROTOCOL = 'http:'  # Replace with 'https:' if you're not using http.

STATICFILES_LOCATION = 'static'
STATIC_URL = "http://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, STATICFILES_LOCATION)
STATICFILES_STORAGE = 'lindshop.utils.custom_storages.CachedS3BotoStorage'

MEDIAFILES_LOCATION = 'media'
MEDIA_URL = "http://%s/%s/" % (AWS_S3_CUSTOM_DOMAIN, MEDIAFILES_LOCATION)
DEFAULT_FILE_STORAGE = 'lindshop.utils.custom_storages.MediaStorage'

lindshop.utils.custom_storages.CachedS3BotoStorage 看起来像这样:

class EuropeConnection(S3Connection):
    DefaultHost = "s3-eu-west-1.amazonaws.com"

class CachedS3BotoStorage(S3BotoStorage):
    connection_class = EuropeConnection
    location = settings.STATICFILES_LOCATION

    def __init__(self, *args, **kwargs):
        super(CachedS3BotoStorage, self).__init__(*args, **kwargs)
        self.local_storage = get_storage_class(
            "compressor.storage.CompressorFileStorage")()

    def save(self, name, content):
        non_gzipped_file_content = content.file
        name = super(CachedS3BotoStorage, self).save(name, content)
        content.file = non_gzipped_file_content
        self.local_storage._save(name, content)
        return name

总结和重复自己。

  1. 我可以从本地主机运行python manage.py collectstatic。我还验证了我可以使用collectstaticcommand 访问 localhost 放置在那里的 S3 实例上的文件。当我在具有相同设置的 Elastic Beanstalk 应用程序中执行相同操作时,我会收到错误消息。
  2. 我之前在其他项目中使用过相同的设置,没有问题。唯一改变的是存储桶名称。
  3. 我在 EB 服务器上运行 collectstatic 时遇到的错误是 S3ResponseError: 301 Moved Permanently

完整追溯:

caused by: Traceback (most recent call last):
  File "/opt/python/run/venv/bin/django-admin.py", line 5, in <module>
  management.execute_from_command_line()
  File "/opt/python/run/venv/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 353, in execute_from_command_line
  utility.execute()
  File "/opt/python/run/venv/local/lib/python2.7/site-packages/django/core/management/__init__.py", line 345, in execute
  self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/opt/python/run/venv/local/lib/python2.7/site-packages/django/core/management/base.py", line 348, in run_from_argv
  self.execute(*args, **cmd_options)
  File "/opt/python/run/venv/local/lib/python2.7/site-packages/django/core/management/base.py", line 399, in execute
  output = self.handle(*args, **options)
  File "/opt/python/run/venv/local/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 176, in handle
  collected = self.collect()
  File "/opt/python/run/venv/local/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 107, in collect
  handler(path, prefixed_path, storage)
  File "/opt/python/run/venv/local/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 325, in copy_file
  if not self.delete_file(path, prefixed_path, source_storage):
  File "/opt/python/run/venv/local/lib/python2.7/site-packages/django/contrib/staticfiles/management/commands/collectstatic.py", line 238, in delete_file
  if self.storage.exists(prefixed_path):
  File "/opt/python/run/venv/local/lib/python2.7/site-packages/storages/backends/s3boto.py", line 446, in exists
  return k.exists()
  File "/opt/python/run/venv/local/lib/python2.7/site-packages/boto/s3/key.py", line 539, in exists
  return bool(self.bucket.lookup(self.name, headers=headers))
  File "/opt/python/run/venv/local/lib/python2.7/site-packages/boto/s3/bucket.py", line 143, in lookup
  return self.get_key(key_name, headers=headers)
  File "/opt/python/run/venv/local/lib/python2.7/site-packages/boto/s3/bucket.py", line 193, in get_key
  key, resp = self._get_key_internal(key_name, headers, query_args_l)
  File "/opt/python/run/venv/local/lib/python2.7/site-packages/boto/s3/bucket.py", line 231, in _get_key_internal
  response.status, response.reason, '')
  boto.exception.S3ResponseError: S3ResponseError: 301 Moved Permanently

   (ElasticBeanstalk::ExternalInvocationError)

【问题讨论】:

  • 请更新您的问题并发布完整的回溯。
  • 此存储桶是否在美国区域之外?
  • 是的,它是在 eu-west-1 中创建的。这就是为什么它使用带有DefaultHost = "s3-eu-west-1.amazonaws.com" 的连接类
  • github.com/boto/boto/issues/443 - 我相信你遇到了这个问题。
  • 当我在本地主机上时,它不使用 IAM 连接到 S3,但是当我在弹性 beantalk 上时,它使用默认的 ec2-user IAM 会不会是这样?我是否需要向 IAM 添加一些权限才能上传/查看 S3?

标签: django amazon-web-services amazon-s3


【解决方案1】:

我发现问题出在我使用的 Django 模块 django-storages 的更新上。在更新中,他们通过以下方式为 S3BotoStorage.host 添加了默认值:

host = setting('AWS_S3_HOST', S3Connection.DefaultHost)

发生的情况是主机自动设置为s3.amazonaws.com,因为它在创建与boto(AWS官方python包)的连接时已经设置了主机,所以它从不使用我的DefaultHost = "s3-eu-west-1.amazonaws.com"添加到我的EuropeConnection-class 中。

解决这个问题的方法是在你的settings.py中设置django-storages设置值AWS_S3_HOST(新)。

AWS_S3_HOST = "s3-eu-west-1.amazonaws.com"

【讨论】:

    猜你喜欢
    • 2014-07-05
    • 2014-06-30
    • 2017-02-28
    • 1970-01-01
    • 2017-06-13
    • 1970-01-01
    • 2014-12-30
    • 2020-10-07
    • 2012-01-09
    相关资源
    最近更新 更多