You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 07:52:55