无法使用Django从S3提供静态媒体文件

3

我需要使用Amazon S3来为我的Django项目提供静态和媒体文件的服务。

然而,我遇到了很多问题。首先是我的代码:

s3utils.py

from storages.backends.s3boto import S3BotoStorage

class FixedS3BotoStorage(S3BotoStorage):
def url(self, name):
    url = super(FixedS3BotoStorage, self).url(name)
    if name.endswith('/') and not url.endswith('/'):
        url += '/'
    return url

StaticS3BotoStorage = lambda: FixedS3BotoStorage(location='static')
MediaS3BotoStorage = lambda: FixedS3BotoStorage(location='media')

settings.py文件中:
DEFAULT_FILE_STORAGE = 'SpareGuru.s3utils.MediaS3BotoStorage'
STATICFILES_STORAGE = 'SpareGuru.s3utils.StaticS3BotoStorage'

AWS_HOST = "s3-ap-southeast-1.amazonaws.com"
AWS_ACCESS_KEY_ID = 'xx'
AWS_SECRET_ACCESS_KEY = 'yy'
AWS_STORAGE_BUCKET_NAME = 'zz'

S3_URL = 'http://%s.s3.amazonaws.com' % AWS_STORAGE_BUCKET_NAME
MEDIA_DIRECTORY = '/media/'
STATIC_DIRECTORY = '/static/'

STATIC_URL = "/static/"

MEDIA_URL = "/media/"

STATIC_ROOT = S3_URL + STATIC_DIRECTORY
COMPRESS_ROOT = STATIC_ROOT
MEDIA_ROOT = S3_URL + MEDIA_DIRECTORY

以下是我面临的问题:
1. 运行./manage.py collectstatic时,它开始上传文件到S3,但在上传几个文件后,我遇到了Broken Pipe错误。
2. 尝试运行网页时,我收到以下错误信息:'https://zz.s3.amazonaws.com/static/css/bootstrap.min.css?Signature=sign&Expires=1438359937&AWSAccessKeyId=xx' isn't accessible via COMPRESS_URL ('/static/') and can't be compressed
对此一无所知。
编辑:我的先前存储桶策略允许只读访问。因此,这可能是我的压缩程序无法在S3上创建文件的原因。我已更新策略,但仍然无法解决问题。更新后的策略如下:
{
"Statement": [
    {
        "Sid": "PublicReadForGetBucketObjects",
        "Effect": "Allow",
        "Principal": {
            "AWS": "*"
        },
        "Action": [
            "s3:GetObject"
        ],
        "Resource": [
            "arn:aws:s3:::zz/*"
        ]
    },
    {
        "Action": "s3:*",
        "Effect": "Allow",
        "Resource": [
            "arn:aws:s3:::zz",
            "arn:aws:s3:::zz/*"
        ],
        "Principal": {
            "AWS": [
                "my-arn:/goes=here"
            ]
        }
    }
]
}

我的存储桶的 CORS 配置 是:

<CORSConfiguration>
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Authorization</AllowedHeader>
    </CORSRule>
</CORSConfiguration>
2个回答

1
我相信您的staticmedia url/根目录是不正确的。它们应该遵循以下格式:
MEDIA_URL = S3_URL + MEDIA_DIRECTORY
STATIC_URL = S3_URL + STATIC_DIRECTORY
MEDIA_ROOT = '/home/host/app/static_root/media'
STATIC_ROOT = '/home/host/app/static_root/static'

注意:将MEDIA_ROOTSTATIC_ROOT更改为您的项目配置方式。 编辑: 抱歉,我没有看到您正在使用压缩器。请尝试执行以下操作:
COMPRESS_URL = S3_URL + STATIC_DIRECTORY
STATIC_URL = COMPRESS_URL
MEDIA_URL = S3_URL + MEDIA_DIRECTORY
MEDIA_ROOT = '/home/host/app/static_root/media'
STATIC_ROOT = '/home/host/app/static_root/static'

尝试按照你所描述的设置 MEDIA_ROOTSTATIC_ROOT,但我仍然收到 Uncompressable FileError - Gaurav Wadhwani
@GauravWadhwani 请看一下我的修改,看看是否有效。 - jape
我已更新存储桶策略(和问题),以允许使用settings.py中凭据的IAM用户创建文件。但它仍然无法工作。 - Gaurav Wadhwani
@GauravWadhwani 在存储桶策略中,将“PublicReadForGetBucketObjects”更改为“AllowPublicRead”。我还会在存储桶策略的同一位置添加一个新的“Authenticated Users”权限,并允许所有特权。如果这样做不起作用,你的CORS配置是什么样子的? - jape
我已经更新了问题,展示了我的 CORS配置。那个单一桶策略中已经有两个策略 - 一个允许公共读取,第二个则授予 主体 所有权限。 - Gaurav Wadhwani

1

我在我的Django项目中使用了这个。我去检查了一下差异。你可以尝试添加以下内容:

AWS_QUERYSTRING_AUTH = False

将其添加到您的settings.py中。这可以至少帮助您解决问题#2。
这是我在settings.py中的完整示例。注意:我不使用S3用于静态文件,只用于媒体文件。
from boto.s3.connection import SubdomainCallingFormat
AWS_CALLING_FORMAT = SubdomainCallingFormat()
DEFAULT_FILE_STORAGE = 'project.s3utils.MediaRootS3BotoStorage'
AWS_ACCESS_KEY_ID = os.getenv('AWS_ACCESS_KEY_ID', None)
AWS_SECRET_ACCESS_KEY = os.getenv('AWS_SECRET_KEY', None)
AWS_SECRET_KEY = os.getenv('AWS_SECRET_KEY')
AWS_STORAGE_BUCKET_NAME = os.getenv('AWS_STORAGE_BUCKET_NAME')
AWS_QUERYSTRING_AUTH = False
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.StaticFilesStorage'
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, '../',  'static')
MEDIA_ROOT = os.path.join(BASE_DIR, '../..',  'media')
MEDIA_URL = 'http://{!s}.s3.amazonaws.com/media/'.format(AWS_STORAGE_BUCKET_NAME)

现在我得到的错误是:'https://zz.s3.amazonaws.com/static/css/bootstrap.min.css' 无法通过 COMPRESS_URL ('/static/') 访问,也无法进行压缩。不同之处在于我不再看到签名或访问密钥 ID。但问题仍然存在,它仍然无法正常工作 :( - Gaurav Wadhwani
也许这是django-compressor的问题?如果您设置:COMPRESS=False会怎样呢? - Brice
使用 COMPRESS_ENABLED = False 禁用压缩器可以使网站正常工作。但是,相同的代码在本地机器上使用压缩可以正常工作,但在 S3 上却不行。 - Gaurav Wadhwani
请尝试添加:AWS_IS_GZIPPED = True - Brice

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接