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

如何使用django-storage SFTP存储后端实现文件下载?

解决Django SFTP文件下载问题的方案

嗨,我来帮你搞定从SFTP服务器下载文件的需求!结合你现有的django-storages配置,这里有几个简单直接的实现方式:

方法一:在现有ViewSet中添加下载动作

最方便的方式是给你的ToolCustomConfigurationsViewSet添加一个自定义的下载动作,利用Django REST Framework的@action装饰器来实现:

修改你的views.py,添加以下代码:

from django.http import FileResponse, HttpResponseNotFound
from rest_framework.decorators import action

class ToolCustomConfigurationsViewSet(viewsets.ModelViewSet):
    queryset = CustomConfigurations.objects.all()
    parser_classes = (FormParser, MultiPartParser,)
    serializer_class = CustomConfigurationsSerializers

    def get_queryset(self):
        queryset = self.queryset.all().order_by('-id')
        return queryset

    # 添加下载动作
    @action(detail=True, methods=['get'])
    def download(self, request, pk=None):
        try:
            # 获取对应的配置实例
            config = self.get_object()
            # 通过SFTPStorage打开远程文件(rb模式读取二进制)
            file_obj = config.file.storage.open(config.file.name, 'rb')
            # 返回下载响应,as_attachment=True触发浏览器下载
            # 用split('/')[-1]提取文件名,避免路径作为下载文件名
            return FileResponse(
                file_obj,
                as_attachment=True,
                filename=config.file.name.split('/')[-1]
            )
        except Exception as e:
            # 捕获文件不存在、SFTP连接失败等异常
            return HttpResponseNotFound("文件不存在或下载失败")

添加完后,你就可以通过GET /your-api-path/configurations/<pk>/download/这个接口来下载对应文件了。如果需要权限控制,还可以给这个action加上权限类,比如:

from rest_framework.permissions import IsAuthenticated

@action(detail=True, methods=['get'], permission_classes=[IsAuthenticated])

方法二:生成下载链接+独立下载视图

如果你希望在序列化的结果中直接返回下载链接,可以先修改序列化器,再写一个独立的下载视图:

1. 修改serializer.py添加下载链接字段

from rest_framework.reverse import reverse

class CustomConfigurationsSerializers(serializers.ModelSerializer):
    download_url = serializers.SerializerMethodField()

    class Meta:
        model = CustomConfigurations
        fields = '__all__'

    def get_download_url(self, obj):
        # 基于当前请求生成绝对下载URL
        return self.context['request'].build_absolute_uri(
            reverse('config-download', kwargs={'pk': obj.pk})
        )

2. 在urls.py中添加下载视图的路由

from django.urls import path
from .views import ConfigDownloadView

urlpatterns = [
    # 你的其他路由...
    path('configurations/<int:pk>/download/', ConfigDownloadView.as_view(), name='config-download'),
]

3. 编写独立的下载视图

from django.views import View
from django.http import FileResponse, HttpResponseNotFound
from .models import CustomConfigurations

class ConfigDownloadView(View):
    def get(self, request, pk):
        try:
            config = CustomConfigurations.objects.get(pk=pk)
            file_obj = config.file.storage.open(config.file.name, 'rb')
            return FileResponse(
                file_obj,
                as_attachment=True,
                filename=config.file.name.split('/')[-1]
            )
        except CustomConfigurations.DoesNotExist:
            return HttpResponseNotFound("对应的配置不存在")
        except Exception as e:
            return HttpResponseNotFound("文件下载失败,请检查SFTP连接或文件权限")

关键注意事项

  • SFTP权限检查:确保你的SFTP账号拥有目标文件的读取权限,同时SFTP服务器的防火墙允许Django服务器的IP访问。
  • 大文件处理:FileResponse会自动流式传输文件,不用担心大文件占用过多内存。
  • 异常处理:可以根据实际需求细化异常捕获,比如捕获IOError、SFTPError等具体异常,返回更精准的错误信息。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:40:29