From e86bf61579c3f6f87acbc05fae360b29450fccfe Mon Sep 17 00:00:00 2001 From: jxxghp Date: Sat, 14 Sep 2024 14:43:14 +0800 Subject: [PATCH] fix storage api --- app/api/endpoints/storage.py | 41 +++++++++++++------- app/chain/storage.py | 4 +- app/modules/filemanager/__init__.py | 16 +++++--- app/modules/filemanager/storages/__init__.py | 4 +- app/modules/filemanager/storages/alipan.py | 11 +++--- app/modules/filemanager/storages/local.py | 4 +- app/modules/filemanager/storages/rclone.py | 10 +++-- app/modules/filemanager/storages/u115.py | 10 +++-- 8 files changed, 63 insertions(+), 37 deletions(-) diff --git a/app/api/endpoints/storage.py b/app/api/endpoints/storage.py index 26f78780c..a793bb356 100644 --- a/app/api/endpoints/storage.py +++ b/app/api/endpoints/storage.py @@ -1,15 +1,16 @@ from pathlib import Path from typing import Any, List -from fastapi import APIRouter, Depends -from starlette.responses import FileResponse +from fastapi import APIRouter, Depends, HTTPException +from starlette.responses import FileResponse, Response from app import schemas from app.chain.storage import StorageChain from app.chain.transfer import TransferChain from app.core.config import settings from app.core.metainfo import MetaInfoPath -from app.core.security import verify_token, verify_uri_token +from app.core.security import verify_token +from app.db.models import User from app.db.user_oper import get_current_active_superuser from app.helper.progress import ProgressHelper from app.schemas.types import ProgressKey @@ -45,7 +46,7 @@ def check(name: str, ck: str = None, t: str = None, _: schemas.TokenPayload = De @router.post("/save/{name}", summary="保存存储配置", response_model=schemas.Response) def save(name: str, conf: dict, - _: schemas.TokenPayload = Depends(get_current_active_superuser)) -> Any: + _: User = Depends(get_current_active_superuser)) -> Any: """ 保存存储配置 """ @@ -56,7 +57,7 @@ def save(name: str, @router.post("/list", summary="所有目录和文件", response_model=List[schemas.FileItem]) def list(fileitem: schemas.FileItem, sort: str = 'updated_at', - _: schemas.TokenPayload = Depends(get_current_active_superuser)) -> Any: + _: User = Depends(get_current_active_superuser)) -> Any: """ 查询当前目录下所有目录和文件 :param fileitem: 文件项 @@ -76,7 +77,7 @@ def list(fileitem: schemas.FileItem, @router.post("/mkdir", summary="创建目录", response_model=schemas.Response) def mkdir(fileitem: schemas.FileItem, name: str, - _: schemas.TokenPayload = Depends(get_current_active_superuser)) -> Any: + _: User = Depends(get_current_active_superuser)) -> Any: """ 创建目录 :param fileitem: 文件项 @@ -93,7 +94,7 @@ def mkdir(fileitem: schemas.FileItem, @router.post("/delete", summary="删除文件或目录", response_model=schemas.Response) def delete(fileitem: schemas.FileItem, - _: schemas.TokenPayload = Depends(get_current_active_superuser)) -> Any: + _: User = Depends(get_current_active_superuser)) -> Any: """ 删除文件或目录 :param fileitem: 文件项 @@ -107,25 +108,39 @@ def delete(fileitem: schemas.FileItem, @router.post("/download", summary="下载文件") def download(fileitem: schemas.FileItem, - _: schemas.TokenPayload = Depends(verify_uri_token)) -> Any: + _: User = Depends(get_current_active_superuser)) -> Any: """ 下载文件或目录 :param fileitem: 文件项 :param _: token """ # 临时目录 - tmp_file = settings.TEMP_PATH / fileitem.name - status = StorageChain().download_file(fileitem, tmp_file) - if status: + tmp_file = StorageChain().download_file(fileitem) + if tmp_file: return FileResponse(path=tmp_file) return schemas.Response(success=False) +@router.post("/image", summary="预览图片") +def image(fileitem: schemas.FileItem, + _: User = Depends(get_current_active_superuser)) -> Any: + """ + 下载文件或目录 + :param fileitem: 文件项 + :param _: token + """ + # 临时目录 + tmp_file = StorageChain().download_file(fileitem) + if not tmp_file: + raise HTTPException(status_code=500, detail="图片读取出错") + return Response(content=tmp_file.read_bytes(), media_type="image/jpeg") + + @router.post("/rename", summary="重命名文件或目录", response_model=schemas.Response) def rename(fileitem: schemas.FileItem, new_name: str, recursive: bool = False, - _: schemas.TokenPayload = Depends(get_current_active_superuser)) -> Any: + _: User = Depends(get_current_active_superuser)) -> Any: """ 重命名文件或目录 :param fileitem: 文件项 @@ -181,7 +196,7 @@ def rename(fileitem: schemas.FileItem, @router.get("/usage/{name}", summary="存储空间信息", response_model=schemas.StorageUsage) -def usage(name: str, _: schemas.TokenPayload = Depends(get_current_active_superuser)) -> Any: +def usage(name: str, _: User = Depends(get_current_active_superuser)) -> Any: """ 查询存储空间 """ diff --git a/app/chain/storage.py b/app/chain/storage.py index 358b348ca..e86e78d74 100644 --- a/app/chain/storage.py +++ b/app/chain/storage.py @@ -40,11 +40,11 @@ def create_folder(self, fileitem: schemas.FileItem, name: str) -> Optional[schem """ return self.run_module("create_folder", fileitem=fileitem, name=name) - def download_file(self, fileitem: schemas.FileItem, path: str) -> Optional[bool]: + def download_file(self, fileitem: schemas.FileItem) -> Optional[Path]: """ 下载文件 """ - return self.run_module("download_file", fileitem=fileitem, path=path) + return self.run_module("download_file", fileitem=fileitem) def upload_file(self, fileitem: schemas.FileItem, path: Path) -> Optional[bool]: """ diff --git a/app/modules/filemanager/__init__.py b/app/modules/filemanager/__init__.py index b89ce7621..bc35f0797 100644 --- a/app/modules/filemanager/__init__.py +++ b/app/modules/filemanager/__init__.py @@ -185,15 +185,15 @@ def rename_file(self, fileitem: FileItem, name: str) -> bool: return False return storage_oper.rename(fileitem, name) - def download_file(self, fileitem: FileItem, path: Path) -> bool: + def download_file(self, fileitem: FileItem) -> Optional[Path]: """ 下载文件 """ storage_oper = self.__get_storage_oper(fileitem.storage) if not storage_oper: logger.error(f"不支持 {fileitem.storage} 的下载处理") - return False - return storage_oper.download(fileitem, path) + return None + return storage_oper.download(fileitem) def upload_file(self, fileitem: FileItem, path: Path) -> Optional[FileItem]: """ @@ -414,13 +414,19 @@ def __get_targetitem(_path: Path) -> FileItem: # 网盘到本地 if transfer_type == "copy": # 下载 - if source_oper.download(fileitem, target_file): + tmp_file = source_oper.download(fileitem) + if tmp_file: + # 将tmp_file移动后target_file + tmp_file.rename(target_file) return __get_targetitem(target_file), "" else: return None, f"{fileitem.path} {fileitem.storage} 下载失败" elif transfer_type == "move": # 下载 - if source_oper.download(fileitem, target_file): + tmp_file = source_oper.download(fileitem) + if tmp_file: + # 将tmp_file移动后target_file + tmp_file.rename(target_file) # 删除源文件 source_oper.delete(fileitem) return __get_targetitem(target_file), "" diff --git a/app/modules/filemanager/storages/__init__.py b/app/modules/filemanager/storages/__init__.py index 2127c2092..376cc6fd4 100644 --- a/app/modules/filemanager/storages/__init__.py +++ b/app/modules/filemanager/storages/__init__.py @@ -96,9 +96,9 @@ def rename(self, fileitm: schemas.FileItem, name: str) -> bool: pass @abstractmethod - def download(self, fileitm: schemas.FileItem, path: Path) -> bool: + def download(self, fileitm: schemas.FileItem) -> Path: """ - 下载文件,保存到本地 + 下载文件,保存到本地,返回本地临时文件地址 """ pass diff --git a/app/modules/filemanager/storages/alipan.py b/app/modules/filemanager/storages/alipan.py index da8a6942a..be2f4b856 100644 --- a/app/modules/filemanager/storages/alipan.py +++ b/app/modules/filemanager/storages/alipan.py @@ -587,13 +587,13 @@ def rename(self, fileitem: schemas.FileItem, name: str) -> bool: self.__handle_error(res, "重命名文件") return False - def download(self, fileitem: schemas.FileItem, path: Path) -> bool: + def download(self, fileitem: schemas.FileItem) -> Optional[Path]: """ 下载文件,保存到本地 """ params = self.__access_params if not params: - return False + return None headers = self.__get_headers(params) res = RequestUtils(headers=headers, timeout=10).post_res(self.download_url, json={ "drive_id": fileitem.drive_id, @@ -602,15 +602,16 @@ def download(self, fileitem: schemas.FileItem, path: Path) -> bool: if res: download_url = res.json().get("url") if not download_url: - return False + return None res = RequestUtils().get_res(download_url) if res: + path = settings.TEMP_PATH / fileitem.name with path.open("wb") as f: f.write(res.content) - return True + return path else: self.__handle_error(res, "获取下载链接") - return False + return None def upload(self, fileitem: schemas.FileItem, path: Path) -> Optional[schemas.FileItem]: """ diff --git a/app/modules/filemanager/storages/local.py b/app/modules/filemanager/storages/local.py index 414b0fba3..4528c0011 100644 --- a/app/modules/filemanager/storages/local.py +++ b/app/modules/filemanager/storages/local.py @@ -177,11 +177,11 @@ def rename(self, fileitem: schemas.FileItem, name: str) -> bool: return False return True - def download(self, fileitem: schemas.FileItem, path: Path) -> bool: + def download(self, fileitem: schemas.FileItem) -> Optional[Path]: """ 下载文件 """ - pass + return Path(fileitem.path) def upload(self, fileitem: schemas.FileItem, path: Path) -> Optional[schemas.FileItem]: """ diff --git a/app/modules/filemanager/storages/rclone.py b/app/modules/filemanager/storages/rclone.py index e59b002a2..1f90448ee 100644 --- a/app/modules/filemanager/storages/rclone.py +++ b/app/modules/filemanager/storages/rclone.py @@ -5,6 +5,7 @@ from typing import Optional, List from app import schemas +from app.core.config import settings from app.log import logger from app.modules.filemanager.storages import StorageBase from app.schemas.types import StorageSchema @@ -225,24 +226,25 @@ def rename(self, fileitm: schemas.FileItem, name: str) -> bool: logger.error(f"rclone重命名文件失败:{err}") return False - def download(self, fileitm: schemas.FileItem, path: Path) -> bool: + def download(self, fileitem: schemas.FileItem) -> Optional[Path]: """ 下载文件 """ + path = settings.TEMP_PATH / fileitem.name try: retcode = subprocess.run( [ 'rclone', 'copyto', - f'MP:{fileitm.path}', + f'MP:{fileitem.path}', f'{path}' ], startupinfo=self.__get_hidden_shell() ).returncode if retcode == 0: - return True + return path except Exception as err: logger.error(f"rclone复制文件失败:{err}") - return False + return None def upload(self, fileitm: schemas.FileItem, path: Path) -> Optional[schemas.FileItem]: """ diff --git a/app/modules/filemanager/storages/u115.py b/app/modules/filemanager/storages/u115.py index f394bb616..23c2082e7 100644 --- a/app/modules/filemanager/storages/u115.py +++ b/app/modules/filemanager/storages/u115.py @@ -8,6 +8,7 @@ from py115.types import LoginTarget, QrcodeSession, QrcodeStatus, Credential from app import schemas +from app.core.config import settings from app.log import logger from app.modules.filemanager.storages import StorageBase from app.schemas.types import StorageSchema @@ -289,23 +290,24 @@ def rename(self, fileitem: schemas.FileItem, name: str) -> bool: logger.error(f"115重命名文件失败:{str(e)}") return False - def download(self, fileitem: schemas.FileItem, path: Path) -> bool: + def download(self, fileitem: schemas.FileItem) -> Optional[Path]: """ 获取下载链接 """ if not self.__init_cloud(): - return False + return None try: ticket = self.cloud.storage().request_download(fileitem.pickcode) if ticket: + path = settings.TEMP_PATH / fileitem.name res = RequestUtils(headers=ticket.headers).get_res(ticket.url) if res: with open(path, "wb") as f: f.write(res.content) - return True + return path except Exception as e: logger.error(f"115下载失败:{str(e)}") - return False + return None def upload(self, fileitem: schemas.FileItem, path: Path) -> Optional[schemas.FileItem]: """