使用AWS S3存储时django-ckeditor5上传图片出现500错误求助
问题描述
在Django站点中使用AWS S3存储桶存储文件,部分模型文本字段采用django-ckeditor5,编辑器上传图片功能在本地存储下正常,但切换到S3后上传图片时终端报错:
OSError: [Errno 30] Read-only file system: '//bucketname.s3.amazonaws.com' [12/Apr/2023 13:33:58] "POST /ckeditor5/image_upload/ HTTP/1.1" 500 118977
已将存储桶策略设置为完全开放,策略内容如下:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AddPerm", "Effect": "Allow", "Principal": "*", "Action": "s3:*", "Resource": "arn:aws:s3:::bucketname/*" } ] }
settings.py中的相关配置片段:
#S3 Bucket config AWS_ACCESS_KEY_ID = 'Key ID here' AWS_SECRET_ACCESS_KEY = 'secret key here' AWS_STORAGE_BUCKET_NAME = 'bucketname' AWS_S3_CUSTOM_DOMAIN = f'{AWS_STORAGE_BUCKET_NAME}.s3.amazonaws.com' #AWS S3 Settings AWS_S3_FILE_OVERWRITE = False AWS_DEFAULT_ACL = None DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage' STATICFILES_STORAGE = 'storages.backends.s3boto3.S3StaticStorage' # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/3.1/howto/static-files/ AWS_LOCATION = 'static' STATICfILES_DIRs = [ str(BASE_DIR.joinpath('static')), ] STATIC_ROOT = BASE_DIR / "static" STATIC_URL = f'https://{AWS_S3_CUSTOM_DOMAIN}/{AWS_LOCATION}/' STATICFILES_FINDERS = ( 'django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder', # other finders.. 'compressor.finders.CompressorFinder', ) MEDIA_URL = '//%s.s3.amazonaws.com/media/' % AWS_STORAGE_BUCKET_NAME MEDIA_ROOT = MEDIA_URL AWS_QUERYSTRING_AUTH = False # needed for ckeditor with S3 AWS_DEFAULT_ACL = 'public-read'
需修复该问题,使图片能上传至存储桶中的正确目录。
修复方案
修正
MEDIA_ROOT配置:你将MEDIA_ROOT设置为S3的URL路径,Django会尝试把这个URL当作本地文件系统路径写入,从而触发只读文件系统错误。直接删除MEDIA_ROOT = MEDIA_URL这一行即可,使用S3存储时无需设置本地路径作为MEDIA_ROOT。自定义媒体存储类(规范做法):在项目根目录创建
storages.py文件,定义专门的媒体存储类来指定S3中的存储前缀:
from storages.backends.s3boto3 import S3Boto3Storage class MediaStorage(S3Boto3Storage): location = 'media' # 指定S3桶中存储媒体文件的目录 file_overwrite = False
然后在settings.py中更新存储配置:
DEFAULT_FILE_STORAGE = '你的项目名.storages.MediaStorage'
这样上传的媒体文件会自动存入S3桶的media目录下。
- 修正静态文件配置的拼写错误:原配置中的
STATICfILES_DIRs存在大小写错误,改为STATICFILES_DIRS,避免静态文件查找异常:
STATICFILES_DIRS = [ str(BASE_DIR.joinpath('static')), ]
统一
AWS_DEFAULT_ACL配置:原配置中先后设置AWS_DEFAULT_ACL = None和AWS_DEFAULT_ACL = 'public-read',保持统一即可,推荐保留'public-read',确保ckeditor能正常访问上传的图片。配置django-ckeditor5的上传路径:在settings.py中添加ckeditor的上传路径配置,指定图片在S3媒体目录下的子路径:
CKEDITOR_UPLOAD_PATH = 'uploads/'
此时上传的图片会存入S3桶的media/uploads/目录中。
内容的提问来源于stack exchange,提问作者Finn
相关产品推荐
相关产品推荐

