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

如何通过Django URL代理CloudFront资源且无重定向、不全量缓存文件

可用开源方案

  • django-proxy:轻量级Django代理组件,原生兼容Django1.11版本,支持流式响应配置,可直接自定义上游请求规则,自动隐藏上游敏感参数(比如你的CloudFront全局签名),不需要自己处理底层传输逻辑。
  • requests + Django原生StreamingHttpResponse:如果不想引入额外的代理依赖,用这两个官方组件即可实现需求,requests的流式请求能力不需要提前下载完整文件到本地。

自行开发实现指引

核心逻辑

你需要实现的是流式反向代理能力,全程边从CloudFront拉取分片数据,边往客户端返回,Django服务端不需要存储完整文件,内存仅保留当前传输的分片,完全避免大文件超时问题。

具体实现步骤

  1. 构造内部CloudFront请求地址
    将用户请求的文件名拼接到CloudFront基础路径后,附上仅服务端可见的files/*全局签名,该地址全程不对外暴露。
  2. 发起流式请求拉取CloudFront资源
    调用requests的get方法时添加stream=True参数,此时requests不会提前下载完整响应体,仅在迭代内容时拉取对应分片:
    import requests
    cloudfront_url = f"some_cloudfront_server://files/{file_name}?{your_global_signature}"
    upstream_resp = requests.get(cloudfront_url, stream=True)
    
  3. 构造流式响应返回客户端
    用Django原生StreamingHttpResponse处理返回,不要使用普通HttpResponse,它会将完整文件加载到服务端内存再返回,会导致大文件超时和内存占用过高问题。将requests返回的内容迭代器直接作为响应体,同时透传CloudFront返回的合法响应头,过滤所有可能泄露内部签名的敏感头:
    from django.http import StreamingHttpResponse
    
    def proxy_file(request, file_name):
        # 先执行你的业务权限校验,确认当前用户有权限访问该资源
        cloudfront_url = f"some_cloudfront_server://files/{file_name}?{your_global_signature}"
        upstream_resp = requests.get(cloudfront_url, stream=True)
        # 透传上游状态码
        if upstream_resp.status_code != 200:
            return Response(status=upstream_resp.status_code)
        # 构造流式响应
        response = StreamingHttpResponse(upstream_resp.iter_content(chunk_size=4096))
        # 透传必要响应头
        response['Content-Type'] = upstream_resp.headers.get('Content-Type', 'application/octet-stream')
        response['Content-Length'] = upstream_resp.headers.get('Content-Length')
        response['Cache-Control'] = upstream_resp.headers.get('Cache-Control', 'no-cache')
        # 可选:配置下载文件名
        response['Content-Disposition'] = f'attachment; filename="{file_name}"'
        return response
    
  4. 集成到DRF ViewSet
    新增自定义action绑定下载路由,注意不要让DRF对响应做额外序列化处理:
    from rest_framework.decorators import action
    from rest_framework.viewsets import ViewSet
    
    class ResourceViewSet(ViewSet):
        @action(methods=['get'], detail=False, url_path=r'download/(?P<file_name>[^/]+)')
        def download(self, request, file_name=None):
            # 上述代理逻辑放在此处
            return response
    

注意事项

  • 可根据业务场景调整chunk_size大小,建议取值范围4KB~8KB,平衡内存占用和传输效率
  • 建议复用requests连接池,减少和CloudFront的连接握手开销,提升传输性能
  • 生产环境高并发场景下,建议配合uWSGI/Gunicorn的异步worker使用,避免阻塞普通业务请求
  • 所有响应头返回前做敏感信息过滤,确保不会泄露内部签名和CloudFront源站地址

内容的提问来源于stack exchange,提问作者Stumbler

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 09:33:01