(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" |
| 920 | ) |
| 921 | |
| 922 | async def stream_generator(): |
| 923 | chunk_size = 65536 |
| 924 | while True: |
| 925 | chunk = await reader.read(chunk_size) |
| 926 | if not chunk: |
| 927 | break |
| 928 | yield chunk |
| 929 | |
| 930 | encoded_filename = quote(filename, safe='') |
| 931 | headers = { |
| 932 | "Content-Disposition": f"attachment; filename*=UTF-8''{encoded_filename}" |
| 933 | } |
| 934 | if content_length is not None: |
| 935 | headers["Content-Length"] = str(content_length) |
| 936 | return StreamingResponse( |
| 937 | stream_generator(), |
| 938 | media_type="application/octet-stream", |
| 939 | headers=headers |
| 940 | ) |
| 941 | except Exception as e: |
| 942 | logger.info(e) |
| 943 | raise HTTPException(status_code=404, detail="文件已过期删除") |
| 944 | |
| 945 | async def save_chunk(self, upload_id: str, chunk_index: int, chunk_data: bytes, chunk_hash: str, save_path: str): |
| 946 | """保存分片到 OpenDAL 存储""" |
nothing calls this directly
no test coverage detected