Skip to content

Commit 31e61f3

Browse files
committed
优化 更新下载,解决下载超时导致失败的问题
1 parent 23f148b commit 31e61f3

File tree

2 files changed

+48
-10
lines changed

2 files changed

+48
-10
lines changed

app/tools/update_utils.py

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import subprocess
99
import sys
1010
import tempfile
11+
import time
1112
from typing import Any, Tuple, Callable, Optional
1213
from loguru import logger
1314
from 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

app/view/settings/update.py

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -534,22 +534,32 @@ def on_download_complete(file_path: Optional[str]):
534534

535535
# 定义下载任务类
536536
class DownloadTask(QRunnable):
537-
def __init__(self, version, progress_callback, on_complete):
537+
def __init__(self, version, progress_callback, on_complete, parent):
538538
super().__init__()
539539
self.version = version
540540
self.progress_callback = progress_callback
541541
self.on_complete = on_complete
542+
self.parent = parent
543+
self.setAutoDelete(True)
542544

543545
def run(self):
544546
"""执行下载任务"""
545-
file_path = download_update(
546-
self.version, progress_callback=self.progress_callback
547-
)
548-
self.on_complete(file_path)
547+
try:
548+
# 增加超时设置和更好的错误处理
549+
file_path = download_update(
550+
self.version,
551+
progress_callback=self.progress_callback,
552+
timeout=300, # 增加超时时间到300秒
553+
)
554+
self.on_complete(file_path)
555+
except Exception as e:
556+
logger.error(f"下载任务执行失败: {e}")
557+
# 确保即使发生异常也会调用完成回调
558+
self.on_complete(None)
549559

550560
# 使用 QThreadPool 执行下载任务
551561
self._download_task = DownloadTask(
552-
latest_version, progress_callback, on_download_complete
562+
latest_version, progress_callback, on_download_complete, self
553563
)
554564
QThreadPool.globalInstance().start(self._download_task)
555565

0 commit comments

Comments
 (0)