mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-04 23:17:20 +08:00
fix(openList): openList file upload and retrieval errors
fix https://github.com/jxxghp/MoviePilot/issues/5369 fix https://github.com/jxxghp/MoviePilot/issues/5038
This commit is contained in:
@@ -17,8 +17,9 @@ from app.utils.url import UrlUtils
|
|||||||
|
|
||||||
class Alist(StorageBase, metaclass=WeakSingleton):
|
class Alist(StorageBase, metaclass=WeakSingleton):
|
||||||
"""
|
"""
|
||||||
Alist相关操作
|
Openlist相关操作
|
||||||
api文档:https://oplist.org/zh/
|
|
||||||
|
API 文档:https://fox.oplist.org/
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# 存储类型
|
# 存储类型
|
||||||
@@ -42,13 +43,19 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
"""
|
"""
|
||||||
self.__generate_token.cache_clear() # noqa
|
self.__generate_token.cache_clear() # noqa
|
||||||
|
|
||||||
def _delay_get_item(self, path: Path) -> Optional[schemas.FileItem]:
|
def _delay_get_item(
|
||||||
|
self, path: Path, /, refresh: bool = False
|
||||||
|
) -> Optional[schemas.FileItem]:
|
||||||
"""
|
"""
|
||||||
自动延迟重试 get_item 模块
|
自动延迟重试 get_item 模块
|
||||||
|
|
||||||
|
:param path: 文件路径
|
||||||
|
:param refresh: 是否刷新
|
||||||
|
:return: 文件项
|
||||||
"""
|
"""
|
||||||
for _ in range(2):
|
for _ in range(2):
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
fileitem = self.get_item(path)
|
fileitem = self.get_item(path=path, refresh=refresh)
|
||||||
if fileitem:
|
if fileitem:
|
||||||
return fileitem
|
return fileitem
|
||||||
return None
|
return None
|
||||||
@@ -66,6 +73,9 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
def __get_api_url(self, path: str) -> str:
|
def __get_api_url(self, path: str) -> str:
|
||||||
"""
|
"""
|
||||||
获取API URL
|
获取API URL
|
||||||
|
|
||||||
|
:param path: API路径
|
||||||
|
:return: API URL
|
||||||
"""
|
"""
|
||||||
return UrlUtils.adapt_request_url(self.__get_base_url, path)
|
return UrlUtils.adapt_request_url(self.__get_base_url, path)
|
||||||
|
|
||||||
@@ -88,14 +98,14 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
token = conf.get("token")
|
token = conf.get("token")
|
||||||
if token:
|
if token:
|
||||||
return str(token)
|
return str(token)
|
||||||
resp = RequestUtils(headers={
|
resp = RequestUtils(headers={"Content-Type": "application/json"}).post_res(
|
||||||
'Content-Type': 'application/json'
|
|
||||||
}).post_res(
|
|
||||||
self.__get_api_url("/api/auth/login"),
|
self.__get_api_url("/api/auth/login"),
|
||||||
data=json.dumps({
|
data=json.dumps(
|
||||||
"username": conf.get("username"),
|
{
|
||||||
"password": conf.get("password"),
|
"username": conf.get("username"),
|
||||||
}),
|
"password": conf.get("password"),
|
||||||
|
}
|
||||||
|
),
|
||||||
)
|
)
|
||||||
"""
|
"""
|
||||||
{
|
{
|
||||||
@@ -117,13 +127,15 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
return ""
|
return ""
|
||||||
|
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
logger.warning(f"【OpenList】更新令牌请求发送失败,状态码:{resp.status_code}")
|
logger.warning(
|
||||||
|
f"【OpenList】更新令牌请求发送失败,状态码:{resp.status_code}"
|
||||||
|
)
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
result = resp.json()
|
result = resp.json()
|
||||||
|
|
||||||
if result["code"] != 200:
|
if result["code"] != 200:
|
||||||
logger.critical(f'【OpenList】更新令牌,错误信息:{result["message"]}')
|
logger.critical(f"【OpenList】更新令牌,错误信息:{result['message']}")
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
logger.debug("【OpenList】AList获取令牌成功")
|
logger.debug("【OpenList】AList获取令牌成功")
|
||||||
@@ -142,12 +154,12 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
return True if self.__generate_token() else False
|
return True if self.__generate_token() else False
|
||||||
|
|
||||||
def list(
|
def list(
|
||||||
self,
|
self,
|
||||||
fileitem: schemas.FileItem,
|
fileitem: schemas.FileItem,
|
||||||
password: Optional[str] = "",
|
password: Optional[str] = "",
|
||||||
page: int = 1,
|
page: int = 1,
|
||||||
per_page: int = 0,
|
per_page: int = 0,
|
||||||
refresh: bool = False,
|
refresh: bool = False,
|
||||||
) -> List[schemas.FileItem]:
|
) -> List[schemas.FileItem]:
|
||||||
"""
|
"""
|
||||||
浏览文件
|
浏览文件
|
||||||
@@ -156,15 +168,14 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
:param page: 页码
|
:param page: 页码
|
||||||
:param per_page: 每页数量
|
:param per_page: 每页数量
|
||||||
:param refresh: 是否刷新
|
:param refresh: 是否刷新
|
||||||
|
:return: 文件列表
|
||||||
"""
|
"""
|
||||||
if fileitem.type == "file":
|
if fileitem.type == "file":
|
||||||
item = self.get_item(Path(fileitem.path))
|
item = self.get_item(Path(fileitem.path))
|
||||||
if item:
|
if item:
|
||||||
return [item]
|
return [item]
|
||||||
return []
|
return []
|
||||||
resp = RequestUtils(
|
resp = RequestUtils(headers=self.__get_header_with_token()).post_res(
|
||||||
headers=self.__get_header_with_token()
|
|
||||||
).post_res(
|
|
||||||
self.__get_api_url("/api/fs/list"),
|
self.__get_api_url("/api/fs/list"),
|
||||||
json={
|
json={
|
||||||
"path": fileitem.path,
|
"path": fileitem.path,
|
||||||
@@ -211,7 +222,9 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
if resp is None:
|
if resp is None:
|
||||||
logger.warn(f"【OpenList】请求获取目录 {fileitem.path} 的文件列表失败,无法连接alist服务")
|
logger.warn(
|
||||||
|
f"【OpenList】请求获取目录 {fileitem.path} 的文件列表失败,无法连接alist服务"
|
||||||
|
)
|
||||||
return []
|
return []
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
@@ -223,7 +236,7 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
|
|
||||||
if result["code"] != 200:
|
if result["code"] != 200:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
f'【OpenList】获取目录 {fileitem.path} 的文件列表失败,错误信息:{result["message"]}'
|
f"【OpenList】获取目录 {fileitem.path} 的文件列表失败,错误信息:{result['message']}"
|
||||||
)
|
)
|
||||||
return []
|
return []
|
||||||
|
|
||||||
@@ -231,7 +244,8 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
schemas.FileItem(
|
schemas.FileItem(
|
||||||
storage=self.schema.value,
|
storage=self.schema.value,
|
||||||
type="dir" if item["is_dir"] else "file",
|
type="dir" if item["is_dir"] else "file",
|
||||||
path=(Path(fileitem.path) / item["name"]).as_posix() + ("/" if item["is_dir"] else ""),
|
path=(Path(fileitem.path) / item["name"]).as_posix()
|
||||||
|
+ ("/" if item["is_dir"] else ""),
|
||||||
name=item["name"],
|
name=item["name"],
|
||||||
basename=Path(item["name"]).stem,
|
basename=Path(item["name"]).stem,
|
||||||
extension=Path(item["name"]).suffix[1:] if not item["is_dir"] else None,
|
extension=Path(item["name"]).suffix[1:] if not item["is_dir"] else None,
|
||||||
@@ -243,17 +257,16 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
]
|
]
|
||||||
|
|
||||||
def create_folder(
|
def create_folder(
|
||||||
self, fileitem: schemas.FileItem, name: str
|
self, fileitem: schemas.FileItem, name: str
|
||||||
) -> Optional[schemas.FileItem]:
|
) -> Optional[schemas.FileItem]:
|
||||||
"""
|
"""
|
||||||
创建目录
|
创建目录
|
||||||
:param fileitem: 父目录
|
:param fileitem: 父目录
|
||||||
:param name: 目录名
|
:param name: 目录名
|
||||||
|
:return: 目录项
|
||||||
"""
|
"""
|
||||||
path = Path(fileitem.path) / name
|
path = Path(fileitem.path) / name
|
||||||
resp = RequestUtils(
|
resp = RequestUtils(headers=self.__get_header_with_token()).post_res(
|
||||||
headers=self.__get_header_with_token()
|
|
||||||
).post_res(
|
|
||||||
self.__get_api_url("/api/fs/mkdir"),
|
self.__get_api_url("/api/fs/mkdir"),
|
||||||
json={"path": path.as_posix()},
|
json={"path": path.as_posix()},
|
||||||
)
|
)
|
||||||
@@ -272,40 +285,50 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
logger.warn(f"【OpenList】请求创建目录 {path} 失败,无法连接alist服务")
|
logger.warn(f"【OpenList】请求创建目录 {path} 失败,无法连接alist服务")
|
||||||
return None
|
return None
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
logger.warn(f"【OpenList】请求创建目录 {path} 失败,状态码:{resp.status_code}")
|
logger.warn(
|
||||||
|
f"【OpenList】请求创建目录 {path} 失败,状态码:{resp.status_code}"
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
result = resp.json()
|
result = resp.json()
|
||||||
if result["code"] != 200:
|
if result["code"] != 200:
|
||||||
logger.warn(f'【OpenList】创建目录 {path} 失败,错误信息:{result["message"]}')
|
logger.warn(
|
||||||
|
f"【OpenList】创建目录 {path} 失败,错误信息:{result['message']}"
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return self._delay_get_item(path)
|
return self._delay_get_item(path, refresh=True)
|
||||||
|
|
||||||
def get_folder(self, path: Path) -> Optional[schemas.FileItem]:
|
def get_folder(self, path: Path) -> Optional[schemas.FileItem]:
|
||||||
"""
|
"""
|
||||||
获取目录,如目录不存在则创建
|
获取目录,如目录不存在则创建
|
||||||
|
|
||||||
|
:param path: 目录路径
|
||||||
|
:return: 目录项
|
||||||
"""
|
"""
|
||||||
folder = self.get_item(path)
|
folder = self.get_item(path)
|
||||||
if folder:
|
if folder:
|
||||||
return folder
|
return folder
|
||||||
if not folder:
|
if not folder:
|
||||||
folder = self.create_folder(schemas.FileItem(
|
folder = self.create_folder(
|
||||||
storage=self.schema.value,
|
schemas.FileItem(
|
||||||
type="dir",
|
storage=self.schema.value,
|
||||||
path=path.parent.as_posix(),
|
type="dir",
|
||||||
name=path.name,
|
path=path.parent.as_posix(),
|
||||||
basename=path.stem
|
name=path.name,
|
||||||
), path.name)
|
basename=path.stem,
|
||||||
|
),
|
||||||
|
path.name,
|
||||||
|
)
|
||||||
return folder
|
return folder
|
||||||
|
|
||||||
def get_item(
|
def get_item(
|
||||||
self,
|
self,
|
||||||
path: Path,
|
path: Path,
|
||||||
password: Optional[str] = "",
|
password: Optional[str] = "",
|
||||||
page: int = 1,
|
page: int = 1,
|
||||||
per_page: int = 0,
|
per_page: int = 0,
|
||||||
refresh: bool = False,
|
refresh: bool = False,
|
||||||
) -> Optional[schemas.FileItem]:
|
) -> Optional[schemas.FileItem]:
|
||||||
"""
|
"""
|
||||||
获取文件或目录,不存在返回None
|
获取文件或目录,不存在返回None
|
||||||
@@ -314,10 +337,9 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
:param page: 页码
|
:param page: 页码
|
||||||
:param per_page: 每页数量
|
:param per_page: 每页数量
|
||||||
:param refresh: 是否刷新
|
:param refresh: 是否刷新
|
||||||
|
:return: 文件项
|
||||||
"""
|
"""
|
||||||
resp = RequestUtils(
|
resp = RequestUtils(headers=self.__get_header_with_token()).post_res(
|
||||||
headers=self.__get_header_with_token()
|
|
||||||
).post_res(
|
|
||||||
self.__get_api_url("/api/fs/get"),
|
self.__get_api_url("/api/fs/get"),
|
||||||
json={
|
json={
|
||||||
"path": path.as_posix(),
|
"path": path.as_posix(),
|
||||||
@@ -362,12 +384,16 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
logger.warn(f"【OpenList】请求获取文件 {path} 失败,无法连接alist服务")
|
logger.warn(f"【OpenList】请求获取文件 {path} 失败,无法连接alist服务")
|
||||||
return None
|
return None
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
logger.warn(f"【OpenList】请求获取文件 {path} 失败,状态码:{resp.status_code}")
|
logger.warn(
|
||||||
|
f"【OpenList】请求获取文件 {path} 失败,状态码:{resp.status_code}"
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
result = resp.json()
|
result = resp.json()
|
||||||
if result["code"] != 200:
|
if result["code"] != 200:
|
||||||
logger.debug(f'【OpenList】获取文件 {path} 失败,错误信息:{result["message"]}')
|
logger.debug(
|
||||||
|
f"【OpenList】获取文件 {path} 失败,错误信息:{result['message']}"
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return schemas.FileItem(
|
return schemas.FileItem(
|
||||||
@@ -385,12 +411,18 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
def get_parent(self, fileitem: schemas.FileItem) -> Optional[schemas.FileItem]:
|
def get_parent(self, fileitem: schemas.FileItem) -> Optional[schemas.FileItem]:
|
||||||
"""
|
"""
|
||||||
获取父目录
|
获取父目录
|
||||||
|
|
||||||
|
:param fileitem: 文件项
|
||||||
|
:return: 父目录项
|
||||||
"""
|
"""
|
||||||
return self.get_folder(Path(fileitem.path).parent)
|
return self.get_folder(Path(fileitem.path).parent)
|
||||||
|
|
||||||
def __is_empty_dir(self, fileitem: schemas.FileItem) -> bool:
|
def __is_empty_dir(self, fileitem: schemas.FileItem) -> bool:
|
||||||
"""
|
"""
|
||||||
判断目录是否为空
|
判断目录是否为空
|
||||||
|
|
||||||
|
:param fileitem: 文件项
|
||||||
|
:return: 是否为空目录
|
||||||
"""
|
"""
|
||||||
if fileitem.type != "dir":
|
if fileitem.type != "dir":
|
||||||
return False
|
return False
|
||||||
@@ -401,19 +433,22 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
def delete(self, fileitem: schemas.FileItem) -> bool:
|
def delete(self, fileitem: schemas.FileItem) -> bool:
|
||||||
"""
|
"""
|
||||||
删除文件或目录,空目录用专用API
|
删除文件或目录,空目录用专用API
|
||||||
|
|
||||||
|
:param fileitem: 文件项
|
||||||
|
:return: 是否删除成功
|
||||||
"""
|
"""
|
||||||
# 如果是空目录,优先用 remove_empty_directory
|
# 如果是空目录,优先用 remove_empty_directory
|
||||||
if fileitem.type == "dir" and self.__is_empty_dir(fileitem):
|
if fileitem.type == "dir" and self.__is_empty_dir(fileitem):
|
||||||
resp = RequestUtils(
|
resp = RequestUtils(headers=self.__get_header_with_token()).post_res(
|
||||||
headers=self.__get_header_with_token()
|
|
||||||
).post_res(
|
|
||||||
self.__get_api_url("/api/fs/remove_empty_directory"),
|
self.__get_api_url("/api/fs/remove_empty_directory"),
|
||||||
json={
|
json={
|
||||||
"src_dir": fileitem.path,
|
"src_dir": fileitem.path,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
if resp is None:
|
if resp is None:
|
||||||
logger.warn(f"【OpenList】请求删除空目录 {fileitem.path} 失败,无法连接alist服务")
|
logger.warn(
|
||||||
|
f"【OpenList】请求删除空目录 {fileitem.path} 失败,无法连接alist服务"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
@@ -423,14 +458,12 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
result = resp.json()
|
result = resp.json()
|
||||||
if result["code"] != 200:
|
if result["code"] != 200:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
f'【OpenList】删除空目录 {fileitem.path} 失败,错误信息:{result["message"]}'
|
f"【OpenList】删除空目录 {fileitem.path} 失败,错误信息:{result['message']}"
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
# 其它情况(文件或非空目录)
|
# 其它情况(文件或非空目录)
|
||||||
resp = RequestUtils(
|
resp = RequestUtils(headers=self.__get_header_with_token()).post_res(
|
||||||
headers=self.__get_header_with_token()
|
|
||||||
).post_res(
|
|
||||||
self.__get_api_url("/api/fs/remove"),
|
self.__get_api_url("/api/fs/remove"),
|
||||||
json={
|
json={
|
||||||
"dir": Path(fileitem.path).parent.as_posix(),
|
"dir": Path(fileitem.path).parent.as_posix(),
|
||||||
@@ -438,7 +471,9 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
if resp is None:
|
if resp is None:
|
||||||
logger.warn(f"【OpenList】请求删除文件 {fileitem.path} 失败,无法连接alist服务")
|
logger.warn(
|
||||||
|
f"【OpenList】请求删除文件 {fileitem.path} 失败,无法连接alist服务"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
@@ -448,7 +483,7 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
result = resp.json()
|
result = resp.json()
|
||||||
if result["code"] != 200:
|
if result["code"] != 200:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
f'【OpenList】删除文件 {fileitem.path} 失败,错误信息:{result["message"]}'
|
f"【OpenList】删除文件 {fileitem.path} 失败,错误信息:{result['message']}"
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
@@ -456,10 +491,12 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
def rename(self, fileitem: schemas.FileItem, name: str) -> bool:
|
def rename(self, fileitem: schemas.FileItem, name: str) -> bool:
|
||||||
"""
|
"""
|
||||||
重命名文件
|
重命名文件
|
||||||
|
|
||||||
|
:param fileitem: 文件项
|
||||||
|
:param name: 新文件名
|
||||||
|
:return: 是否重命名成功
|
||||||
"""
|
"""
|
||||||
resp = RequestUtils(
|
resp = RequestUtils(headers=self.__get_header_with_token()).post_res(
|
||||||
headers=self.__get_header_with_token()
|
|
||||||
).post_res(
|
|
||||||
self.__get_api_url("/api/fs/rename"),
|
self.__get_api_url("/api/fs/rename"),
|
||||||
json={
|
json={
|
||||||
"name": name,
|
"name": name,
|
||||||
@@ -479,7 +516,9 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
}
|
}
|
||||||
"""
|
"""
|
||||||
if not resp:
|
if not resp:
|
||||||
logger.warn(f"【OpenList】请求重命名文件 {fileitem.path} 失败,无法连接alist服务")
|
logger.warn(
|
||||||
|
f"【OpenList】请求重命名文件 {fileitem.path} 失败,无法连接alist服务"
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
@@ -490,27 +529,26 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
result = resp.json()
|
result = resp.json()
|
||||||
if result["code"] != 200:
|
if result["code"] != 200:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
f'【OpenList】重命名文件 {fileitem.path} 失败,错误信息:{result["message"]}'
|
f"【OpenList】重命名文件 {fileitem.path} 失败,错误信息:{result['message']}"
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def download(
|
def download(
|
||||||
self,
|
self,
|
||||||
fileitem: schemas.FileItem,
|
fileitem: schemas.FileItem,
|
||||||
path: Path = None,
|
path: Path = None,
|
||||||
password: Optional[str] = "",
|
password: Optional[str] = "",
|
||||||
) -> Optional[Path]:
|
) -> Optional[Path]:
|
||||||
"""
|
"""
|
||||||
下载文件,保存到本地,返回本地临时文件地址
|
下载文件,保存到本地,返回本地临时文件地址
|
||||||
:param fileitem: 文件项
|
:param fileitem: 文件项
|
||||||
:param path: 文件保存路径
|
:param path: 文件保存路径
|
||||||
:param password: 文件密码
|
:param password: 文件密码
|
||||||
|
:return: 本地临时文件地址
|
||||||
"""
|
"""
|
||||||
resp = RequestUtils(
|
resp = RequestUtils(headers=self.__get_header_with_token()).post_res(
|
||||||
headers=self.__get_header_with_token()
|
|
||||||
).post_res(
|
|
||||||
self.__get_api_url("/api/fs/get"),
|
self.__get_api_url("/api/fs/get"),
|
||||||
json={
|
json={
|
||||||
"path": fileitem.path,
|
"path": fileitem.path,
|
||||||
@@ -547,18 +585,24 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
logger.warn(f"【OpenList】请求获取文件 {path} 失败,无法连接alist服务")
|
logger.warn(f"【OpenList】请求获取文件 {path} 失败,无法连接alist服务")
|
||||||
return None
|
return None
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
logger.warn(f"【OpenList】请求获取文件 {path} 失败,状态码:{resp.status_code}")
|
logger.warn(
|
||||||
|
f"【OpenList】请求获取文件 {path} 失败,状态码:{resp.status_code}"
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
result = resp.json()
|
result = resp.json()
|
||||||
if result["code"] != 200:
|
if result["code"] != 200:
|
||||||
logger.warn(f'【OpenList】获取文件 {path} 失败,错误信息:{result["message"]}')
|
logger.warn(
|
||||||
|
f"【OpenList】获取文件 {path} 失败,错误信息:{result['message']}"
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if result["data"]["raw_url"]:
|
if result["data"]["raw_url"]:
|
||||||
download_url = result["data"]["raw_url"]
|
download_url = result["data"]["raw_url"]
|
||||||
else:
|
else:
|
||||||
download_url = UrlUtils.adapt_request_url(self.__get_base_url, f"/d{fileitem.path}")
|
download_url = UrlUtils.adapt_request_url(
|
||||||
|
self.__get_base_url, f"/d{fileitem.path}"
|
||||||
|
)
|
||||||
if result["data"]["sign"]:
|
if result["data"]["sign"]:
|
||||||
download_url = download_url + "?sign=" + result["data"]["sign"]
|
download_url = download_url + "?sign=" + result["data"]["sign"]
|
||||||
|
|
||||||
@@ -585,7 +629,11 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
return local_path
|
return local_path
|
||||||
|
|
||||||
def upload(
|
def upload(
|
||||||
self, fileitem: schemas.FileItem, path: Path, new_name: Optional[str] = None, task: bool = False
|
self,
|
||||||
|
fileitem: schemas.FileItem,
|
||||||
|
path: Path,
|
||||||
|
new_name: Optional[str] = None,
|
||||||
|
task: bool = False,
|
||||||
) -> Optional[schemas.FileItem]:
|
) -> Optional[schemas.FileItem]:
|
||||||
"""
|
"""
|
||||||
上传文件(带进度)
|
上传文件(带进度)
|
||||||
@@ -593,6 +641,7 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
:param path: 本地文件路径
|
:param path: 本地文件路径
|
||||||
:param new_name: 上传后文件名
|
:param new_name: 上传后文件名
|
||||||
:param task: 是否为任务,默认为False避免未完成上传时对文件进行操作
|
:param task: 是否为任务,默认为False避免未完成上传时对文件进行操作
|
||||||
|
:return: 上传后的文件项
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
# 获取文件大小
|
# 获取文件大小
|
||||||
@@ -612,7 +661,7 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
# 创建自定义的文件流,支持进度回调
|
# 创建自定义的文件流,支持进度回调
|
||||||
class ProgressFileReader:
|
class ProgressFileReader:
|
||||||
def __init__(self, file_path: Path, callback):
|
def __init__(self, file_path: Path, callback):
|
||||||
self.file = open(file_path, 'rb')
|
self.file = open(file_path, "rb")
|
||||||
self.callback = callback
|
self.callback = callback
|
||||||
self.uploaded_size = 0
|
self.uploaded_size = 0
|
||||||
self.file_size = file_path.stat().st_size
|
self.file_size = file_path.stat().st_size
|
||||||
@@ -638,7 +687,7 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
# 使用自定义文件流上传
|
# 使用自定义文件流上传
|
||||||
progress_reader = ProgressFileReader(path, progress_callback)
|
progress_reader = ProgressFileReader(path, progress_callback)
|
||||||
try:
|
try:
|
||||||
resp = RequestUtils(headers=headers).put_res(
|
resp = RequestUtils(headers=headers, timeout=6000).put_res(
|
||||||
self.__get_api_url("/api/fs/put"),
|
self.__get_api_url("/api/fs/put"),
|
||||||
data=progress_reader,
|
data=progress_reader,
|
||||||
)
|
)
|
||||||
@@ -649,17 +698,21 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
logger.warn(f"【OpenList】请求上传文件 {path} 失败")
|
logger.warn(f"【OpenList】请求上传文件 {path} 失败")
|
||||||
return None
|
return None
|
||||||
if resp.status_code != 200:
|
if resp.status_code != 200:
|
||||||
logger.warn(f"【OpenList】请求上传文件 {path} 失败,状态码:{resp.status_code}")
|
logger.warn(
|
||||||
|
f"【OpenList】请求上传文件 {path} 失败,状态码:{resp.status_code}"
|
||||||
|
)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# 完成上传
|
# 完成上传
|
||||||
progress_callback(100)
|
progress_callback(100)
|
||||||
|
|
||||||
# 获取上传后的文件项
|
# 获取上传后的文件项
|
||||||
new_item = self._delay_get_item(target_path)
|
new_item = self._delay_get_item(target_path, refresh=True)
|
||||||
if new_item and new_name and new_name != path.name:
|
if new_item and new_name and new_name != path.name:
|
||||||
if self.rename(new_item, new_name):
|
if self.rename(new_item, new_name):
|
||||||
return self._delay_get_item(Path(new_item.path).with_name(new_name))
|
return self._delay_get_item(
|
||||||
|
Path(new_item.path).with_name(new_name), refresh=True
|
||||||
|
)
|
||||||
|
|
||||||
return new_item
|
return new_item
|
||||||
|
|
||||||
@@ -679,10 +732,9 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
:param fileitem: 文件项
|
:param fileitem: 文件项
|
||||||
:param path: 目标目录
|
:param path: 目标目录
|
||||||
:param new_name: 新文件名
|
:param new_name: 新文件名
|
||||||
|
:return: 是否复制成功
|
||||||
"""
|
"""
|
||||||
resp = RequestUtils(
|
resp = RequestUtils(headers=self.__get_header_with_token()).post_res(
|
||||||
headers=self.__get_header_with_token()
|
|
||||||
).post_res(
|
|
||||||
self.__get_api_url("/api/fs/copy"),
|
self.__get_api_url("/api/fs/copy"),
|
||||||
json={
|
json={
|
||||||
"src_dir": Path(fileitem.path).parent.as_posix(),
|
"src_dir": Path(fileitem.path).parent.as_posix(),
|
||||||
@@ -719,12 +771,12 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
result = resp.json()
|
result = resp.json()
|
||||||
if result["code"] != 200:
|
if result["code"] != 200:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
f'【OpenList】复制文件 {fileitem.path} 失败,错误信息:{result["message"]}'
|
f"【OpenList】复制文件 {fileitem.path} 失败,错误信息:{result['message']}"
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
# 重命名
|
# 重命名
|
||||||
if fileitem.name != new_name:
|
if fileitem.name != new_name:
|
||||||
new_item = self._delay_get_item(path / fileitem.name)
|
new_item = self._delay_get_item(path / fileitem.name, refresh=True)
|
||||||
if new_item:
|
if new_item:
|
||||||
self.rename(new_item, new_name)
|
self.rename(new_item, new_name)
|
||||||
return True
|
return True
|
||||||
@@ -735,13 +787,12 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
:param fileitem: 文件项
|
:param fileitem: 文件项
|
||||||
:param path: 目标目录
|
:param path: 目标目录
|
||||||
:param new_name: 新文件名
|
:param new_name: 新文件名
|
||||||
|
:return: 是否移动成功
|
||||||
"""
|
"""
|
||||||
# 先重命名
|
# 先重命名
|
||||||
if fileitem.name != new_name:
|
if fileitem.name != new_name:
|
||||||
self.rename(fileitem, new_name)
|
self.rename(fileitem, new_name)
|
||||||
resp = RequestUtils(
|
resp = RequestUtils(headers=self.__get_header_with_token()).post_res(
|
||||||
headers=self.__get_header_with_token()
|
|
||||||
).post_res(
|
|
||||||
self.__get_api_url("/api/fs/move"),
|
self.__get_api_url("/api/fs/move"),
|
||||||
json={
|
json={
|
||||||
"src_dir": Path(fileitem.path).parent.as_posix(),
|
"src_dir": Path(fileitem.path).parent.as_posix(),
|
||||||
@@ -778,7 +829,7 @@ class Alist(StorageBase, metaclass=WeakSingleton):
|
|||||||
result = resp.json()
|
result = resp.json()
|
||||||
if result["code"] != 200:
|
if result["code"] != 200:
|
||||||
logger.warn(
|
logger.warn(
|
||||||
f'【OpenList】移动文件 {fileitem.path} 失败,错误信息:{result["message"]}'
|
f"【OpenList】移动文件 {fileitem.path} 失败,错误信息:{result['message']}"
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|||||||
Reference in New Issue
Block a user