fix storage

This commit is contained in:
jxxghp
2024-07-01 11:57:32 +08:00
parent 302514a469
commit 964e212831
7 changed files with 100 additions and 29 deletions

View File

@@ -14,6 +14,7 @@ from app.helper.message import MessageHelper
from app.helper.module import ModuleHelper
from app.log import logger
from app.modules import _ModuleBase
from app.modules.filemanager.storage import StorageBase
from app.schemas import TransferInfo, ExistMediaInfo, TmdbEpisode, MediaDirectory, FileItem
from app.schemas.types import MediaType
from app.utils.system import SystemUtils
@@ -230,12 +231,12 @@ class FileManagerModule(_ModuleBase):
episodes_info=episodes_info,
need_scrape=need_scrape)
def __get_storage_oper(self, storage: str):
def __get_storage_oper(self, _storage: str):
"""
获取存储操作对象
"""
for storage_schema in self._storage_schemas:
if storage_schema.schema == storage:
if storage_schema.schema == _storage:
return storage_schema()
return None
@@ -259,9 +260,9 @@ class FileManagerModule(_ModuleBase):
logger.error(f"不支持 {fileitem.storage}{target_storage} 的文件整理")
return False
# 源操作对象
source_oper = self.__get_storage_oper(fileitem.storage)
source_oper: StorageBase = self.__get_storage_oper(fileitem.storage)
# 目的操作对象
target_oper = self.__get_storage_oper(target_storage)
target_oper: StorageBase = self.__get_storage_oper(target_storage)
with lock:
if fileitem.storage == "local" and target_storage == "local":
# 本地到本地
@@ -281,18 +282,19 @@ class FileManagerModule(_ModuleBase):
if not filepath.exists():
logger.error(f"文件 {filepath} 不存在")
return False
# TODO 根据目的路径创建文件夹
# 根据目的路径创建文件夹
target_fileitem = target_oper.get_folder(target_file.parent)
if target_fileitem:
# 上传文件
return target_oper.upload(target_fileitem, filepath)
if target_oper.upload(target_fileitem, filepath):
return True
elif transfer_type == "move":
# 移动
filepath = Path(fileitem.path)
if not filepath.exists():
logger.error(f"文件 {filepath} 不存在")
return False
# TODO 根据目的路径获取文件夹
# 根据目的路径获取文件夹
target_fileitem = target_oper.get_folder(target_file.parent)
if target_fileitem:
# 上传文件

View File

@@ -1,6 +1,6 @@
from abc import ABCMeta, abstractmethod
from pathlib import Path
from typing import Optional, List, Any
from typing import Optional, List
from app import schemas
@@ -109,7 +109,7 @@ class StorageBase(metaclass=ABCMeta):
pass
@abstractmethod
def softlink(self, fileitm: schemas.FileItem, target_file: schemas.FileItem) -> bool:
def softlink(self, fileitm: schemas.FileItem, target_file: Path) -> bool:
"""
软链接文件
"""

View File

@@ -331,8 +331,7 @@ class AliPan(StorageBase):
self.__handle_error(res, "获取用户信息")
return {}
def list(self, drive_id: str = None, parent_file_id: str = 'root', list_type: str = None,
limit: int = 100, order_by: str = 'updated_at', path: str = "/") -> List[schemas.FileItem]:
def list(self, fileitem: schemas.FileItem = None) -> List[schemas.FileItem]:
"""
浏览文件
limit 返回文件数量,默认 50最大 100
@@ -346,10 +345,11 @@ class AliPan(StorageBase):
# 请求头
headers = self.__get_headers(params)
# 根目录处理
if not drive_id:
if not fileitem or not fileitem.drive_id:
return [
schemas.FileItem(
fileid=parent_file_id,
storage=self.schema.value,
fileid=fileitem.fileid,
drive_id=params.get("resourceDriveId"),
parent_fileid="root",
type="dir",
@@ -357,7 +357,8 @@ class AliPan(StorageBase):
name="资源库"
),
schemas.FileItem(
fileid=parent_file_id,
storage=self.schema.value,
fileid=fileitem.fileid,
drive_id=params.get("backDriveId"),
parent_fileid="root",
type="dir",
@@ -370,13 +371,12 @@ class AliPan(StorageBase):
# 分页获取
next_marker = None
while True:
if not parent_file_id or parent_file_id == "/":
if not fileitem.parent_fileid or fileitem.parent_fileid == "/":
parent_file_id = "root"
else:
parent_file_id = fileitem.fileid
res = RequestUtils(headers=headers, timeout=10).post_res(self.list_file_url, json={
"drive_id": drive_id,
"type": list_type,
"limit": limit,
"order_by": order_by,
"drive_id": fileitem.drive_id,
"parent_file_id": parent_file_id,
"marker": next_marker
}, params={
@@ -400,10 +400,11 @@ class AliPan(StorageBase):
self.__handle_error(res, "浏览文件")
break
return [schemas.FileItem(
storage=self.schema.value,
fileid=fileinfo.get("file_id"),
parent_fileid=fileinfo.get("parent_file_id"),
type="dir" if fileinfo.get("type") == "folder" else "file",
path=f"{path}{fileinfo.get('name')}" + ("/" if fileinfo.get("type") == "folder" else ""),
path=f"{fileitem.path}{fileinfo.get('name')}" + ("/" if fileinfo.get("type") == "folder" else ""),
name=fileinfo.get("name"),
size=fileinfo.get("size"),
extension=fileinfo.get("file_extension"),
@@ -441,6 +442,7 @@ class AliPan(StorageBase):
"""
result = res.json()
return schemas.FileItem(
storage=self.schema.value,
fileid=result.get("file_id"),
drive_id=result.get("drive_id"),
parent_fileid=result.get("parent_file_id"),
@@ -454,9 +456,36 @@ class AliPan(StorageBase):
def get_folder(self, path: Path) -> Optional[schemas.FileItem]:
"""
TODO 获取目录,不存在则创建
根据文件路程获取目录,不存在则创建
"""
pass
def __find_dir_name(_fileitem: schemas.FileItem, _name: str) -> Optional[schemas.FileItem]:
"""
查找下级目录中匹配名称的目录
"""
sub_files = self.list(_fileitem)
for sub_file in sub_files:
if sub_file.type != "dir":
continue
if sub_file.name == _name:
return sub_file
return None
# 逐级查找和创建目录
fileitem = schemas.FileItem(fileid="root")
for part in path.parts:
if part == "/":
continue
dir_file = __find_dir_name(fileitem, part)
if dir_file:
return dir_file
else:
dir_file = self.create_folder(dir_file, part)
if not dir_file:
logger.warn(f"创建 aplipan 目录 {fileitem.path}{part} 失败!")
return None
fileitem = dir_file
return None
def delete(self, fileitem: schemas.FileItem) -> bool:
"""
@@ -491,6 +520,7 @@ class AliPan(StorageBase):
if res:
result = res.json()
return schemas.FileItem(
storage=self.schema.value,
fileid=result.get("file_id"),
drive_id=result.get("drive_id"),
parent_fileid=result.get("parent_file_id"),
@@ -582,6 +612,7 @@ class AliPan(StorageBase):
if result.get("exist"):
logger.info(f"文件{result.get('file_name')}已存在,无需上传")
return schemas.FileItem(
storage=self.schema.value,
drive_id=result.get("drive_id"),
fileid=result.get("file_id"),
parent_fileid=result.get("parent_file_id"),
@@ -616,6 +647,7 @@ class AliPan(StorageBase):
return None
result = res.json()
return schemas.FileItem(
storage=self.schema.value,
fileid=result.get("file_id"),
drive_id=result.get("drive_id"),
parent_fileid=result.get("parent_file_id"),
@@ -659,7 +691,7 @@ class AliPan(StorageBase):
"""
pass
def softlink(self, fileitm: schemas.FileItem, target_file: schemas.FileItem) -> bool:
def softlink(self, fileitm: schemas.FileItem, target_file: Path) -> bool:
"""
软链接文件
"""

View File

@@ -42,6 +42,7 @@ class LocalStorage(StorageBase):
partitions = SystemUtils.get_windows_drives() or ["C:/"]
for partition in partitions:
ret_items.append(schemas.FileItem(
storage=self.schema.value,
type="dir",
path=partition + "/",
name=partition,
@@ -65,6 +66,7 @@ class LocalStorage(StorageBase):
# 如果是文件
if path_obj.is_file():
ret_items.append(schemas.FileItem(
storage=self.schema.value,
type="file",
path=str(path_obj).replace("\\", "/"),
name=path_obj.name,
@@ -78,6 +80,7 @@ class LocalStorage(StorageBase):
# 扁历所有目录
for item in SystemUtils.list_sub_directory(path_obj):
ret_items.append(schemas.FileItem(
storage=self.schema.value,
type="dir",
path=str(item).replace("\\", "/") + "/",
name=item.name,
@@ -88,6 +91,7 @@ class LocalStorage(StorageBase):
# 遍历所有文件,不含子目录
for item in SystemUtils.list_sub_all(path_obj):
ret_items.append(schemas.FileItem(
storage=self.schema.value,
type="file",
path=str(item).replace("\\", "/"),
name=item.name,
@@ -108,6 +112,7 @@ class LocalStorage(StorageBase):
if not path_obj.exists():
path_obj.mkdir(parents=True, exist_ok=True)
return schemas.FileItem(
storage=self.schema.value,
type="dir",
path=str(path_obj).replace("\\", "/") + "/",
name=name,
@@ -127,6 +132,7 @@ class LocalStorage(StorageBase):
"""
path_obj = Path(fileitm.path)
return schemas.FileItem(
storage=self.schema.value,
type="file",
path=str(path_obj).replace("\\", "/"),
name=path_obj.name,
@@ -178,6 +184,7 @@ class LocalStorage(StorageBase):
filepath.rename(path)
if path.exists():
return schemas.FileItem(
storage=self.schema.value,
type="file",
path=str(path).replace("\\", "/"),
name=path.name,

View File

@@ -103,5 +103,5 @@ class Rclone(StorageBase):
def link(self, fileitm: schemas.FileItem, target_file: Path) -> bool:
pass
def softlink(self, fileitm: schemas.FileItem, target_file: schemas.FileItem) -> bool:
def softlink(self, fileitm: schemas.FileItem, target_file: Path) -> bool:
pass

View File

@@ -162,8 +162,9 @@ class U115Pan(StorageBase, metaclass=Singleton):
if not self.__init_cloud():
return None
try:
items = self.cloud.storage().list(dir_id=fileitem.parent_fileid)
items = self.cloud.storage().list(dir_id=fileitem.fileid)
return [schemas.FileItem(
storage=self.schema.value,
fileid=item.file_id,
parent_fileid=item.parent_id,
type="dir" if item.is_dir else "file",
@@ -187,6 +188,7 @@ class U115Pan(StorageBase, metaclass=Singleton):
try:
result = self.cloud.storage().make_dir(fileitem.parent_fileid, name)
return schemas.FileItem(
storage=self.schema.value,
fileid=result.file_id,
parent_fileid=result.parent_id,
type="dir",
@@ -201,9 +203,36 @@ class U115Pan(StorageBase, metaclass=Singleton):
def get_folder(self, path: Path) -> Optional[schemas.FileItem]:
"""
TODO 获取目录,不存在则创建
根据文件路程获取目录,不存在则创建
"""
pass
def __find_dir_name(_fileitem: schemas.FileItem, _name: str) -> Optional[schemas.FileItem]:
"""
查找下级目录中匹配名称的目录
"""
sub_files = self.list(_fileitem)
for sub_file in sub_files:
if sub_file.type != "dir":
continue
if sub_file.name == _name:
return sub_file
return None
# 逐级查找和创建目录
fileitem = schemas.FileItem(fileid="0")
for part in path.parts:
if part == "/":
continue
dir_file = __find_dir_name(fileitem, part)
if dir_file:
return dir_file
else:
dir_file = self.create_folder(dir_file, part)
if not dir_file:
logger.warn(f"创建 115 目录 {fileitem.path}{part} 失败!")
return None
fileitem = dir_file
return None
def detail(self, fileitm: schemas.FileItem) -> Optional[schemas.FileItem]:
"""
@@ -286,6 +315,7 @@ class U115Pan(StorageBase, metaclass=Singleton):
fileitem = result.get('data')
logger.info(f"115上传文件成功{fileitem}")
return schemas.FileItem(
storage=self.schema.value,
fileid=fileitem.get('file_id'),
parent_fileid=fileitem.fileid,
type="file",
@@ -321,5 +351,5 @@ class U115Pan(StorageBase, metaclass=Singleton):
def link(self, fileitm: schemas.FileItem, target_file: Path) -> bool:
pass
def softlink(self, fileitm: schemas.FileItem, target_file: schemas.FileItem) -> bool:
def softlink(self, fileitm: schemas.FileItem, target_file: Path) -> bool:
pass

View File

@@ -9,7 +9,7 @@ class FileItem(BaseModel):
# 类型 dir/file
type: Optional[str] = None
# 文件路径
path: Optional[str] = None
path: Optional[str] = "/"
# 文件名
name: Optional[str] = None
# 文件名