MCPcopy Create free account
hub / github.com/vastsa/FileCodeBox / WebDAVFileStorage

Class WebDAVFileStorage

core/storage.py:1013–1327  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1011
1012
1013class WebDAVFileStorage(FileStorageInterface):
1014 _instance: Optional["WebDAVFileStorage"] = None
1015
1016 def __init__(self):
1017 if not hasattr(self, "_initialized"):
1018 self.base_url = settings.webdav_url.rstrip("/") + "/"
1019 self.auth = aiohttp.BasicAuth(
1020 login=settings.webdav_username, password=settings.webdav_password
1021 )
1022 self._initialized = True
1023
1024 def _build_url(self, path: str) -> str:
1025 encoded_path = quote(str(path.replace("\\", "/").lstrip("/")).lstrip("/"))
1026 return f"{self.base_url}{encoded_path}"
1027
1028 async def _mkdir_p(self, directory_path: str):
1029 """递归创建目录(类似mkdir -p)"""
1030 path_obj = Path(unquote(directory_path))
1031 current_path = ""
1032
1033 async with aiohttp.ClientSession(auth=self.auth) as session:
1034 # 逐级检查目录是否存在
1035 for part in path_obj.parts:
1036 current_path = str(Path(current_path) / part)
1037 url = self._build_url(current_path)
1038
1039 # 检查目录是否存在
1040 async with session.head(url) as resp:
1041 if resp.status == 404:
1042 # 创建目录
1043 async with session.request("MKCOL", url) as mkcol_resp:
1044 if mkcol_resp.status not in (200, 201, 409):
1045 content = await mkcol_resp.text()
1046 raise HTTPException(
1047 status_code=mkcol_resp.status,
1048 detail=f"目录创建失败: {content[:200]}",
1049 )
1050
1051 async def _is_dir_empty(self, dir_path: str) -> bool:
1052 """检查目录是否为空"""
1053 url = self._build_url(dir_path)
1054
1055 async with aiohttp.ClientSession(auth=self.auth) as session:
1056 async with session.request("PROPFIND", url, headers={"Depth": "1"}) as resp:
1057 if resp.status != 207: # 207 是 Multi-Status 响应
1058 return False
1059 content = await resp.text()
1060 # 如果只有一个 response(当前目录),说明目录为空
1061 return content.count("<D:response>") <= 1
1062
1063 async def _delete_empty_dirs(self, file_path: str, session: aiohttp.ClientSession):
1064 """递归删除空目录"""
1065 path_obj = Path(file_path)
1066 current_path = path_obj.parent
1067
1068 while str(current_path) != ".":
1069 if not await self._is_dir_empty(str(current_path)):
1070 break

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected