"""文档文件来源解析器。""" from __future__ import annotations from dataclasses import dataclass from pathlib import Path from fastapi_common.fastapi_common_logger import logger from fastapi_common.fastapi_common_storage.oss_client import OssClient from fastapi_modules.fastapi_leaudit.models.leauditDocumentFile import LeauditDocumentFile @dataclass(frozen=True) class FileSourcePayload: """可供执行链消费的文件载荷。""" fileName: str fileContent: bytes sourceType: str sourcePath: str | None = None class FileSourceResolver: """解析文档文件来源。""" def __init__(self, Oss: OssClient | None = None) -> None: self.Oss = Oss or OssClient() async def ResolvePayload(self, DocumentFile: LeauditDocumentFile) -> FileSourcePayload: """解析文档文件,返回任务入口可直接消费的字节载荷。""" if DocumentFile.localPath: LocalPath = Path(DocumentFile.localPath) if LocalPath.is_file(): return FileSourcePayload( fileName=DocumentFile.fileName, fileContent=LocalPath.read_bytes(), sourceType="local", sourcePath=str(LocalPath), ) if DocumentFile.ossUrl: return await self._DownloadFromUrl( FileName=DocumentFile.fileName, Url=DocumentFile.ossUrl, ) raise ValueError("当前文档文件既无可用 localPath,也无可用 ossUrl") async def ResolvePayloads(self, DocumentFiles: list[LeauditDocumentFile]) -> list[FileSourcePayload]: """批量解析文档文件。""" payloads: list[FileSourcePayload] = [] for documentFile in DocumentFiles: payloads.append(await self.ResolvePayload(documentFile)) return payloads async def _DownloadFromUrl(self, FileName: str, Url: str) -> FileSourcePayload: """从 OSS 或 URL 下载文件内容。""" try: Content = self.Oss.DownloadBytes(Url) except Exception as Error: logger.error(f"下载 OSS 文件失败: url={Url}, error={Error}") raise return FileSourcePayload( fileName=FileName, fileContent=Content, sourceType="oss", sourcePath=Url, )