diff --git a/core/storage.py b/core/storage.py index 085f64a..dc957d5 100644 --- a/core/storage.py +++ b/core/storage.py @@ -409,6 +409,34 @@ class WebDAVFileStorage(FileStorageInterface): detail=f"目录创建失败: {content[:200]}", ) + async def _is_dir_empty(self, dir_path: str) -> bool: + """检查目录是否为空""" + url = self._build_url(dir_path) + + async with aiohttp.ClientSession(auth=self.auth) as session: + async with session.request("PROPFIND", url, headers={"Depth": "1"}) as resp: + if resp.status != 207: # 207 是 Multi-Status 响应 + return False + content = await resp.text() + # 如果只有一个 response(当前目录),说明目录为空 + return content.count("") <= 1 + + async def _delete_empty_dirs(self, file_path: str, session: aiohttp.ClientSession): + """递归删除空目录""" + path_obj = Path(file_path) + current_path = path_obj.parent + + while str(current_path) != ".": + if not await self._is_dir_empty(str(current_path)): + break + + url = self._build_url(str(current_path)) + async with session.delete(url) as resp: + if resp.status not in (200, 204, 404): + break + + current_path = current_path.parent + async def save_file(self, file: UploadFile, save_path: str): """保存文件(自动创建目录)""" # 分离文件名和目录路径 @@ -437,19 +465,24 @@ class WebDAVFileStorage(FileStorageInterface): raise HTTPException(status_code=503, detail=f"WebDAV连接异常: {str(e)}") async def delete_file(self, file_code: FileCodes): - """删除WebDAV文件""" + """删除WebDAV文件及空目录""" file_path = await file_code.get_file_path() url = self._build_url(file_path) try: async with aiohttp.ClientSession(auth=self.auth) as session: + # 删除文件 async with session.delete(url) as resp: - if resp.status not in (200, 204): + if resp.status not in (200, 204, 404): content = await resp.text() raise HTTPException( status_code=resp.status, detail=f"WebDAV删除失败: {content[:200]}", ) + + # 使用同一个 session 删除空目录 + await self._delete_empty_dirs(file_path, session) + except aiohttp.ClientError as e: raise HTTPException(status_code=503, detail=f"WebDAV连接异常: {str(e)}")