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

Class OpenDALFileStorage

core/storage.py:862–1010  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

860
861
862class OpenDALFileStorage(FileStorageInterface):
863 def __init__(self):
864 try:
865 import opendal
866 except ImportError:
867 raise ImportError('请先安装 `opendal`, 例如: "pip install opendal"')
868 self.service = settings.opendal_scheme
869 service_settings = {}
870 for key, value in settings.items():
871 if key.startswith("opendal_" + self.service):
872 setting_name = key.split("_", 2)[2]
873 service_settings[setting_name] = value
874 self.operator = opendal.AsyncOperator(
875 settings.opendal_scheme, **service_settings
876 )
877
878 async def save_file(self, file: UploadFile, save_path: str):
879 # 使用 asyncio.to_thread 避免阻塞事件循环
880 content = await asyncio.to_thread(file.file.read)
881 await self.operator.write(save_path, content)
882
883 async def delete_file(self, file_code: FileCodes):
884 await self.operator.delete(await file_code.get_file_path())
885
886 async def get_file_url(self, file_code: FileCodes):
887 return await get_file_url(file_code.code)
888
889 async def get_file_response(self, file_code: FileCodes):
890 try:
891 filename = file_code.prefix + file_code.suffix
892 content_length = None # 初始化为 None,表示未知大小
893
894 # 尝试获取文件大小
895 try:
896 stat_result = await self.operator.stat(await file_code.get_file_path())
897 if hasattr(stat_result, 'content_length') and stat_result.content_length:
898 content_length = stat_result.content_length
899 elif hasattr(stat_result, 'size') and stat_result.size:
900 content_length = stat_result.size
901 except Exception:
902 # 如果获取大小失败,则不提供 Content-Length
903 pass
904
905 # 尝试使用流式读取器
906 try:
907 # OpenDAL 可能提供 reader 方法返回一个异步读取器
908 reader = await self.operator.reader(await file_code.get_file_path())
909 except AttributeError:
910 # 如果 reader 方法不存在,回退到全量读取(兼容旧版本)
911 content = await self.operator.read(await file_code.get_file_path())
912 encoded_filename = quote(filename, safe='')
913 headers = {
914 "Content-Disposition": f"attachment; filename*=UTF-8''{encoded_filename}"
915 }
916 if content_length is not None:
917 headers["Content-Length"] = str(content_length)
918 return Response(
919 content, headers=headers, media_type="application/octet-stream"

Callers

nothing calls this directly

Calls

no outgoing calls

Tested by

no test coverage detected