mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-02-12 06:55:46 +08:00
fix storage api
This commit is contained in:
@@ -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:
|
||||
"""
|
||||
查询存储空间
|
||||
"""
|
||||
|
||||
@@ -40,11 +40,11 @@ class StorageChain(ChainBase):
|
||||
"""
|
||||
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]:
|
||||
"""
|
||||
|
||||
@@ -185,15 +185,15 @@ class FileManagerModule(_ModuleBase):
|
||||
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 @@ class FileManagerModule(_ModuleBase):
|
||||
# 网盘到本地
|
||||
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), ""
|
||||
|
||||
@@ -96,9 +96,9 @@ class StorageBase(metaclass=ABCMeta):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
def download(self, fileitm: schemas.FileItem, path: Path) -> bool:
|
||||
def download(self, fileitm: schemas.FileItem) -> Path:
|
||||
"""
|
||||
下载文件,保存到本地
|
||||
下载文件,保存到本地,返回本地临时文件地址
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
@@ -587,13 +587,13 @@ class AliPan(StorageBase):
|
||||
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 @@ class AliPan(StorageBase):
|
||||
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]:
|
||||
"""
|
||||
|
||||
@@ -177,11 +177,11 @@ class LocalStorage(StorageBase):
|
||||
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]:
|
||||
"""
|
||||
|
||||
@@ -5,6 +5,7 @@ from pathlib import Path
|
||||
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 @@ class Rclone(StorageBase):
|
||||
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]:
|
||||
"""
|
||||
|
||||
@@ -8,6 +8,7 @@ from py115 import Cloud
|
||||
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 @@ class U115Pan(StorageBase, metaclass=Singleton):
|
||||
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]:
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user