保存文件(自动创建目录,流式上传)
(self, file: UploadFile, save_path: str)
| 1077 | current_path = current_path.parent |
| 1078 | |
| 1079 | async def save_file(self, file: UploadFile, save_path: str): |
| 1080 | """保存文件(自动创建目录,流式上传)""" |
| 1081 | path_obj = Path(save_path) |
| 1082 | directory_path = str(path_obj.parent) |
| 1083 | # 提取原始文件名并进行清理 |
| 1084 | filename = await sanitize_filename(path_obj.name) |
| 1085 | # 构建安全的保存路径 |
| 1086 | safe_save_path = str(Path(directory_path) / filename) |
| 1087 | |
| 1088 | try: |
| 1089 | # 先创建目录结构 |
| 1090 | await self._mkdir_p(directory_path) |
| 1091 | # 上传文件(流式) |
| 1092 | url = self._build_url(safe_save_path) |
| 1093 | |
| 1094 | async def file_sender(): |
| 1095 | """流式读取文件内容""" |
| 1096 | chunk_size = 256 * 1024 # 256KB chunks |
| 1097 | while True: |
| 1098 | chunk = await asyncio.to_thread(file.file.read, chunk_size) |
| 1099 | if not chunk: |
| 1100 | break |
| 1101 | yield chunk |
| 1102 | |
| 1103 | async with aiohttp.ClientSession(auth=self.auth) as session: |
| 1104 | async with session.put( |
| 1105 | url, |
| 1106 | data=file_sender(), |
| 1107 | headers={"Content-Type": file.content_type or "application/octet-stream"} |
| 1108 | ) as resp: |
| 1109 | if resp.status not in (200, 201, 204): |
| 1110 | content = await resp.text() |
| 1111 | raise HTTPException( |
| 1112 | status_code=resp.status, |
| 1113 | detail=f"文件上传失败: {content[:200]}", |
| 1114 | ) |
| 1115 | except aiohttp.ClientError as e: |
| 1116 | raise HTTPException( |
| 1117 | status_code=503, detail=f"WebDAV连接异常: {str(e)}") |
| 1118 | |
| 1119 | async def delete_file(self, file_code: FileCodes): |
| 1120 | """删除WebDAV文件及空目录""" |
nothing calls this directly
no test coverage detected