如何使用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
相关产品推荐
相关产品推荐

