@@ -144,10 +144,19 @@ async def get_file_response(self, file_code: FileCodes):
144144 filename = f"{ file_code .prefix } { file_code .suffix } "
145145 encoded_filename = quote (filename , safe = '' )
146146 content_disposition = f"attachment; filename*=UTF-8''{ encoded_filename } "
147+
148+ # 优先使用文件系统大小
149+ content_length = file_code .size # 默认使用数据库中的大小
150+ try :
151+ content_length = file_path .stat ().st_size
152+ except Exception :
153+ # 如果获取文件大小失败,继续使用默认大小
154+ pass
155+
147156 return FileResponse (
148157 file_path ,
149158 media_type = "application/octet-stream" ,
150- headers = {"Content-Disposition" : content_disposition , "Content-Length" : str (file_code . size )},
159+ headers = {"Content-Disposition" : content_disposition , "Content-Length" : str (content_length )},
151160 filename = filename # 保留原始文件名以备某些场景使用
152161 )
153162
@@ -296,12 +305,29 @@ async def delete_file(self, file_code: FileCodes):
296305 async def get_file_response (self , file_code : FileCodes ):
297306 try :
298307 filename = file_code .prefix + file_code .suffix
308+ content_length = file_code .size # 默认使用数据库中的大小
309+
299310 async with self .session .client (
300311 "s3" ,
301312 endpoint_url = self .endpoint_url ,
302313 region_name = self .region_name ,
303314 config = Config (signature_version = self .signature_version ),
304315 ) as s3 :
316+ # 首先尝试获取文件大小(HEAD请求)
317+ try :
318+ head_response = await s3 .head_object (
319+ Bucket = self .bucket_name ,
320+ Key = await file_code .get_file_path ()
321+ )
322+ # 从HEAD响应中获取Content-Length
323+ if 'ContentLength' in head_response :
324+ content_length = head_response ['ContentLength' ]
325+ elif 'Content-Length' in head_response ['ResponseMetadata' ]['HTTPHeaders' ]:
326+ content_length = int (head_response ['ResponseMetadata' ]['HTTPHeaders' ]['Content-Length' ])
327+ except Exception :
328+ # 如果HEAD请求失败,继续使用默认大小
329+ pass
330+
305331 link = await s3 .generate_presigned_url (
306332 "get_object" ,
307333 Params = {
@@ -330,7 +356,7 @@ async def stream_generator():
330356 from fastapi .responses import StreamingResponse
331357 headers = {
332358 "Content-Disposition" : f'attachment; filename="{ filename .encode ("utf-8" ).decode ("latin-1" )} "' ,
333- "Content-Length" : str (file_code . size )
359+ "Content-Length" : str (content_length )
334360 }
335361 return StreamingResponse (
336362 stream_generator (),
@@ -618,6 +644,18 @@ async def get_file_response(self, file_code: FileCodes):
618644 self ._get_file_url , await file_code .get_file_path (), filename
619645 )
620646
647+ content_length = file_code .size # 默认使用数据库中的大小
648+
649+ # 尝试发送HEAD请求获取Content-Length
650+ try :
651+ async with aiohttp .ClientSession () as session :
652+ async with session .head (link ) as resp :
653+ if resp .status == 200 and 'Content-Length' in resp .headers :
654+ content_length = int (resp .headers ['Content-Length' ])
655+ except Exception :
656+ # 如果HEAD请求失败,继续使用默认大小
657+ pass
658+
621659 async def stream_generator ():
622660 async with aiohttp .ClientSession () as session :
623661 async with session .get (link ) as resp :
@@ -635,7 +673,7 @@ async def stream_generator():
635673
636674 headers = {
637675 "Content-Disposition" : f'attachment; filename="{ filename .encode ("utf-8" ).decode ("latin-1" )} "' ,
638- "Content-Length" : str (file_code . size )
676+ "Content-Length" : str (content_length )
639677 }
640678 return StreamingResponse (
641679 stream_generator (),
@@ -804,6 +842,19 @@ async def get_file_url(self, file_code: FileCodes):
804842 async def get_file_response (self , file_code : FileCodes ):
805843 try :
806844 filename = file_code .prefix + file_code .suffix
845+ content_length = file_code .size # 默认使用数据库中的大小
846+
847+ # 尝试获取文件大小
848+ try :
849+ stat_result = await self .operator .stat (await file_code .get_file_path ())
850+ if hasattr (stat_result , 'content_length' ) and stat_result .content_length :
851+ content_length = stat_result .content_length
852+ elif hasattr (stat_result , 'size' ) and stat_result .size :
853+ content_length = stat_result .size
854+ except Exception :
855+ # 如果获取大小失败,继续使用默认大小
856+ pass
857+
807858 # 尝试使用流式读取器
808859 try :
809860 # OpenDAL 可能提供 reader 方法返回一个异步读取器
@@ -813,7 +864,7 @@ async def get_file_response(self, file_code: FileCodes):
813864 content = await self .operator .read (await file_code .get_file_path ())
814865 headers = {
815866 "Content-Disposition" : f'attachment; filename="{ filename } "' ,
816- "Content-Length" : str (file_code . size )
867+ "Content-Length" : str (content_length )
817868 }
818869 return Response (
819870 content , headers = headers , media_type = "application/octet-stream"
@@ -829,7 +880,7 @@ async def stream_generator():
829880
830881 headers = {
831882 "Content-Disposition" : f'attachment; filename="{ filename } "' ,
832- "Content-Length" : str (file_code . size )
883+ "Content-Length" : str (content_length )
833884 }
834885 return StreamingResponse (
835886 stream_generator (),
@@ -1023,6 +1074,19 @@ async def get_file_response(self, file_code: FileCodes):
10231074 try :
10241075 filename = file_code .prefix + file_code .suffix
10251076 url = self ._build_url (await file_code .get_file_path ())
1077+ content_length = file_code .size # 默认使用数据库中的大小
1078+
1079+ # 尝试发送HEAD请求获取Content-Length
1080+ try :
1081+ async with aiohttp .ClientSession (headers = {
1082+ "Authorization" : f"Basic { base64 .b64encode (f'{ settings .webdav_username } :{ settings .webdav_password } ' .encode ()).decode ()} "
1083+ }) as session :
1084+ async with session .head (url ) as resp :
1085+ if resp .status == 200 and 'Content-Length' in resp .headers :
1086+ content_length = int (resp .headers ['Content-Length' ])
1087+ except Exception :
1088+ # 如果HEAD请求失败,继续使用默认大小
1089+ pass
10261090
10271091 async def stream_generator ():
10281092 async with aiohttp .ClientSession (headers = {
@@ -1043,7 +1107,7 @@ async def stream_generator():
10431107
10441108 headers = {
10451109 "Content-Disposition" : f'attachment; filename="{ filename .encode ("utf-8" ).decode ()} "' ,
1046- "Content-Length" : str (file_code . size )
1110+ "Content-Length" : str (content_length )
10471111 }
10481112 return StreamingResponse (
10491113 stream_generator (),
0 commit comments