Django-Storages配置SFTP存储后GET请求访问媒体文件失败
问题根因
你配置的DEFAULT_FILE_STORAGE仅作用于文件写入逻辑,Django默认的静态媒体读取规则仍会按照MEDIA_URL+本地MEDIA_ROOT的逻辑处理资源请求,自然找不到存在远程SFTP存储盒的文件。你之前删除static配置后仍然404,是因为此时/media/开头的请求没有对应的路由处理逻辑,自然返回404。
解决方案
- 方案1:直接使用存储盒对外访问地址(推荐)
Hetzner存储盒本身支持HTTPS公开访问,你只需修改settings.py中的MEDIA_URL配置为存储盒对应媒体目录的访问前缀即可:
MEDIA_URL = 'https://你的存储盒用户名.your-storagebox.de/media/'
同时开启存储盒/media目录的公开访问权限,前端会直接向存储盒请求资源,无需经过Django服务,性能最优。
- 方案2:Django代理读取资源
如果不希望存储盒直接对外暴露,可自行实现媒体资源读取视图,从SFTP存储拉取文件后返回给前端:
首先新增视图函数:
from django.http import HttpResponse, Http404 from storages.backends.sftpstorage import SFTPStorage def serve_sftp_media(request, path): sftp_sto = SFTPStorage() if not sftp_sto.exists(path): raise Http404("资源不存在") with sftp_sto.open(path, 'rb') as f: content = f.read() # 可根据文件后缀动态设置Content-Type resp = HttpResponse(content) if path.lower().endswith(('.jpg', '.jpeg')): resp['Content-Type'] = 'image/jpeg' elif path.lower().endswith('.png'): resp['Content-Type'] = 'image/png' elif path.lower().endswith('.gif'): resp['Content-Type'] = 'image/gif' return resp
然后修改urls.py,删除原来的static(settings.MEDIA_URL...)配置,新增路由:
path('media/<path:path>', serve_sftp_media),
该方案仅适合低流量场景,高并发下会占用大量Django服务资源,建议配合缓存使用。
- 方案3:反向代理层转发
如果使用Nginx、Apache等反向代理服务,可直接在代理层配置规则,将/media/开头的请求直接转发到Hetzner存储盒的对应地址,性能介于方案1和方案2之间,同时避免存储盒地址直接对外暴露。
内容的提问来源于stack exchange,提问作者Sarius
相关产品推荐
相关产品推荐

