feat: 支持文件上传下载备份 (#10438)

* feat: 支持文件上传下载备份

* perf: 抽离replay和ftpfile存储代码

* perf: FTPLog增加session字段

* fix: 修改变量名
This commit is contained in:
jiangweidong
2023-06-08 18:04:07 +08:00
committed by GitHub
parent 271ec1bfe0
commit 2837dcf40e
19 changed files with 294 additions and 103 deletions

View File

@@ -22,15 +22,13 @@ from common.drf.renders import PassthroughRenderer
from common.api import AsyncApiMixin
from common.utils import data_to_json, is_uuid
from common.utils import get_logger, get_object_or_none
from common.storage.replay import ReplayStorageHandler
from rbac.permissions import RBACPermission
from orgs.mixins.api import OrgBulkModelViewSet
from orgs.utils import tmp_to_root_org, tmp_to_org
from terminal import serializers
from terminal.models import Session
from terminal.utils import (
find_session_replay_local, download_session_replay,
is_session_approver, get_session_replay_url
)
from terminal.utils import is_session_approver
from terminal.permissions import IsSessionAssignee
from users.models import User
@@ -112,20 +110,23 @@ class SessionViewSet(OrgBulkModelViewSet):
os.chdir(current_dir)
return file
def get_storage(self):
return ReplayStorageHandler(self.get_object())
@action(methods=[GET], detail=True, renderer_classes=(PassthroughRenderer,), url_path='replay/download',
url_name='replay-download')
def download(self, request, *args, **kwargs):
session = self.get_object()
local_path, url = get_session_replay_url(session)
storage = self.get_storage()
local_path, url_or_err = storage.get_file_path_url()
if local_path is None:
return Response({"error": url}, status=404)
file = self.prepare_offline_file(session, local_path)
return Response({'error': url_or_err}, status=404)
file = self.prepare_offline_file(storage.obj, local_path)
response = FileResponse(file)
response['Content-Type'] = 'application/octet-stream'
# 这里要注意哦网上查到的方法都是response['Content-Disposition']='attachment;filename="filename.py"',
# 但是如果文件名是英文名没问题如果文件名包含中文下载下来的文件名会被改为url中的path。
filename = escape_uri_path('{}.tar'.format(session.id))
filename = escape_uri_path('{}.tar'.format(storage.obj.id))
disposition = "attachment; filename*=UTF-8''{}".format(filename)
response["Content-Disposition"] = disposition
return response
@@ -208,13 +209,12 @@ class SessionReplayViewSet(AsyncApiMixin, viewsets.ViewSet):
def retrieve(self, request, *args, **kwargs):
session_id = kwargs.get('pk')
session = get_object_or_404(Session, id=session_id)
local_path, url = find_session_replay_local(session)
if not local_path:
local_path, url = download_session_replay(session)
if not local_path:
return Response({"error": url}, status=404)
data = self.get_replay_data(session, url)
storage = ReplayStorageHandler(session)
local_path, url_or_err = storage.get_file_path_url()
if url_or_err:
return Response({"error": url_or_err}, status=404)
data = self.get_replay_data(session, url_or_err)
return Response(data)