2016-07-12 79 views
3

我正在運行將所有靜態和媒體文件添加到Amazon S3的Django項目。我正在使用過去多次使用過的settings.py配置,以及其他多個項目的工作方式(下面會發布)。Django在S3ResponseError中收集靜態結果:301永久移動

當我在我自己的本地主機上使用相同的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。我也驗證了我可以通過collectstatic命令訪問本地主機已經在那裏安裝的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) 
+0

請更新您的問題併發布完整的回溯。 –

+0

這個桶是否在美國地區之外? –

+0

是的,它創建於歐盟西部1區。這就是爲什麼它使用'DefaultHost =「s3-eu-west-1.amazonaws.com」' –

回答

4

我想通了,這個問題是因爲更新Django的模塊django-storages,我用。在更新他們通過下列方式分配給它添加了一個默認值S3BotoStorage.host

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

什麼情況是,主機會自動設置爲s3.amazonaws.com因爲它已經有一個主機組時,它會創建連接與boto(AWS官方python-package),它從不使用我在EuropeConnection-classes中添加的DefaultHost = "s3-eu-west-1.amazonaws.com"

解決此問題的方法是在您的settings.py中設置django-storage設置值AWS_S3_HOST(新增)。

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