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

如何在Django视图中实现从S3下载文件的功能

Django实现S3文件下载的解决方案

核心思路

你现有的函数依赖本地文件路径读取文件,但S3上的对象没有本地存储路径,不需要走本地IO逻辑,直接调用S3的SDK读取对象流或者生成临时访问链接即可实现需求。

前置准备

  • 安装AWS官方SDK:pip install boto3
  • 在Django settings中配置S3凭证(生产环境推荐通过IAM角色、环境变量传递凭证,不要硬编码密钥):
# settings.py
AWS_ACCESS_KEY_ID = "你的S3访问密钥ID"
AWS_SECRET_ACCESS_KEY = "你的S3秘密访问密钥"
AWS_S3_REGION_NAME = "你的S3区域,例如ap-beijing"
AWS_STORAGE_BUCKET_NAME = "你的S3存储桶名称"

方案1:Django代理下载(适配原函数逻辑)

和你现有写法逻辑一致,Django先从S3拉取文件流再返回给客户端,适合小文件场景:

import boto3
from django.conf import settings
from django.http import HttpResponse, Http404

def download(request):
    # 初始化S3客户端
    s3 = boto3.client(
        's3',
        aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
        aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
        region_name=settings.AWS_S3_REGION_NAME
    )
    s3_file_key = "S3上的文件路径,例如docs/2024/订单.pdf"
    base_name_edi = "用户下载时展示的文件名,例如2024年6月订单.pdf"
    
    try:
        # 直接从S3获取文件对象
        s3_response = s3.get_object(Bucket=settings.AWS_STORAGE_BUCKET_NAME, Key=s3_file_key)
        # 读取S3返回的文件流生成响应,无需存本地
        response = HttpResponse(s3_response['Body'].read())
        # 保持原有响应头配置
        response['Content-Disposition'] = f'inline; filename={base_name_edi}'
        # 可选:设置正确的文件类型,避免下载时格式识别错误
        response['Content-Type'] = s3_response['ContentType']
        return response
    except s3.exceptions.NoSuchKey:
        raise Http404("请求的文件不存在")

方案2:S3预签名URL下载(推荐,节省服务器资源)

大文件场景优先选用该方案,不需要Django转发文件流,直接生成有时效性的S3临时访问链接,让客户端直接跳转下载,大幅降低服务器带宽消耗:

import boto3
from django.conf import settings
from django.shortcuts import redirect

def download(request):
    s3 = boto3.client(
        's3',
        aws_access_key_id=settings.AWS_ACCESS_KEY_ID,
        aws_secret_access_key=settings.AWS_SECRET_ACCESS_KEY,
        region_name=settings.AWS_S3_REGION_NAME
    )
    s3_file_key = "S3上的文件路径,例如docs/2024/订单.pdf"
    base_name_edi = "用户下载时展示的文件名,例如2024年6月订单.pdf"
    
    # 生成有效期为3600秒(1小时)的预签名下载链接
    presigned_url = s3.generate_presigned_url(
        ClientMethod='get_object',
        Params={
            'Bucket': settings.AWS_STORAGE_BUCKET_NAME,
            'Key': s3_file_key,
            'ResponseContentDisposition': f'inline; filename={base_name_edi}'
        },
        ExpiresIn=3600
    )
    # 直接重定向到S3临时链接即可完成下载
    return redirect(presigned_url)

注意事项

  • 如果你使用的是阿里云OSS、腾讯云COS等兼容S3协议的对象存储,只需要在初始化s3客户端时加上endpoint_url参数指定服务地址即可,其余逻辑完全通用
  • 预签名URL的有效期可根据业务需求调整,使用IAM用户签名的情况下最长不超过7天

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 06:45:03