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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 10:12:03