88import subprocess
99import sys
1010import tempfile
11+ import time
1112from typing import Any , Tuple , Callable , Optional
1213from loguru import logger
1314from app .tools .path_utils import *
@@ -389,6 +390,7 @@ async def download_update_async(
389390 arch : str = ARCH ,
390391 struct : str = STRUCT ,
391392 progress_callback : Optional [Callable ] = None ,
393+ timeout : int = 300 , # 增加超时参数,默认300秒
392394) -> Optional [str ]:
393395 """
394396 异步下载更新文件
@@ -399,6 +401,7 @@ async def download_update_async(
399401 arch (str, optional): 架构,默认为当前架构
400402 struct (str, optional): 结构,默认为当前结构
401403 progress_callback (Optional[Callable]): 进度回调函数,接收已下载字节数和总字节数
404+ timeout (int, optional): 下载超时时间(秒),默认300秒
402405
403406 Returns:
404407 Optional[str]: 下载完成的文件路径,如果下载失败则返回 None
@@ -422,33 +425,56 @@ async def download_update_async(
422425 ensure_dir (download_dir )
423426 file_path = download_dir / file_name
424427
428+ # 配置客户端超时设置
429+ client_timeout = aiohttp .ClientTimeout (
430+ total = timeout , # 总超时时间
431+ connect = 30 , # 连接超时时间
432+ sock_read = 60 , # 读取超时时间
433+ sock_connect = 30 , # Socket连接超时时间
434+ )
435+
425436 # 发送异步请求
426- async with aiohttp .ClientSession () as session :
437+ async with aiohttp .ClientSession (timeout = client_timeout ) as session :
427438 async with session .get (
428- download_url , timeout = 60 , allow_redirects = True
439+ download_url ,
440+ allow_redirects = True ,
441+ headers = {"User-Agent" : "SecRandom Update Client" },
429442 ) as response :
430443 response .raise_for_status ()
431444
432445 # 获取文件总大小
433446 total_size = int (response .headers .get ("Content-Length" , 0 ))
434447 downloaded_size = 0
448+ last_progress_time = time .time ()
435449
436450 # 开始下载文件
437451 with open (file_path , "wb" ) as f :
438- async for chunk in response .content .iter_chunked (8192 ):
452+ # 使用更大的块大小提高下载速度
453+ async for chunk in response .content .iter_chunked (32768 ):
439454 if not chunk :
440455 break
441456
442457 # 写入文件
443458 f .write (chunk )
444459 downloaded_size += len (chunk )
460+ last_progress_time = time .time ()
445461
446462 # 调用进度回调函数
447463 if progress_callback :
448464 progress_callback (downloaded_size , total_size )
449465
450466 logger .debug (f"更新文件下载成功: { file_path } " )
451467 return file_path
468+ except aiohttp .ClientTimeout as e :
469+ logger .error (f"下载超时: { e } " )
470+ return None
471+ except aiohttp .ClientError as e :
472+ logger .error (f"HTTP请求失败: { e } " )
473+ # 尝试使用不同的超时策略重试一次
474+ logger .info ("尝试使用更长超时时间重试下载..." )
475+ return await download_update_async (
476+ version , system , arch , struct , progress_callback , timeout = timeout * 2
477+ )
452478 except Exception as e :
453479 logger .error (f"下载更新文件失败: { e } " )
454480 return None
@@ -460,6 +486,7 @@ def download_update(
460486 arch : str = ARCH ,
461487 struct : str = STRUCT ,
462488 progress_callback : Optional [Callable ] = None ,
489+ timeout : int = 300 , # 增加超时参数,默认300秒
463490) -> Optional [str ]:
464491 """
465492 下载更新文件(同步版本)
@@ -470,12 +497,13 @@ def download_update(
470497 arch (str, optional): 架构,默认为当前架构
471498 struct (str, optional): 结构,默认为当前结构
472499 progress_callback (Optional[Callable]): 进度回调函数,接收已下载字节数和总字节数
500+ timeout (int, optional): 下载超时时间(秒),默认300秒
473501
474502 Returns:
475503 Optional[str]: 下载完成的文件路径,如果下载失败则返回 None
476504 """
477505 return _run_async_func (
478- download_update_async , version , system , arch , struct , progress_callback
506+ download_update_async , version , system , arch , struct , progress_callback , timeout
479507 )
480508
481509
0 commit comments