From d382ac4fa2677b2513639653f469672d297faae2 Mon Sep 17 00:00:00 2001 From: CJKmkp <2564608840@qq.com> Date: Tue, 22 Jul 2025 18:02:29 +0800 Subject: [PATCH] =?UTF-8?q?improve:=E8=87=AA=E5=8A=A8=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Ink Canvas/Helpers/AutoUpdateHelper.cs | 57 ++++++------ Ink Canvas/MainWindow.xaml.cs | 2 +- Ink Canvas/Windows/HasNewUpdateWindow.xaml.cs | 91 ++----------------- 3 files changed, 42 insertions(+), 108 deletions(-) diff --git a/Ink Canvas/Helpers/AutoUpdateHelper.cs b/Ink Canvas/Helpers/AutoUpdateHelper.cs index 2cc8864a..01e3d327 100644 --- a/Ink Canvas/Helpers/AutoUpdateHelper.cs +++ b/Ink Canvas/Helpers/AutoUpdateHelper.cs @@ -32,7 +32,7 @@ namespace Ink_Canvas.Helpers } // 通道-线路组映射 - private static readonly Dictionary> ChannelLineGroups = new Dictionary> + public static readonly Dictionary> ChannelLineGroups = new Dictionary> { { UpdateChannel.Release, new List { @@ -371,7 +371,8 @@ namespace Ink_Canvas.Helpers } // 主要的更新检测方法(优先检测延迟,失败时自动切换线路组) - public static async Task<(string remoteVersion, UpdateLineGroup lineGroup, string releaseNotes, string directDownloadUrl)> CheckForUpdates(UpdateChannel channel = UpdateChannel.Release, bool alwaysGetRemote = false) + // 仅检测新版本时用GitHub API,实际下载时只用线路组 + public static async Task<(string remoteVersion, UpdateLineGroup lineGroup, string releaseNotes)> CheckForUpdates(UpdateChannel channel = UpdateChannel.Release, bool alwaysGetRemote = false) { try { @@ -379,28 +380,23 @@ namespace Ink_Canvas.Helpers LogHelper.WriteLogToFile($"AutoUpdate | 本地版本: {localVersion}"); LogHelper.WriteLogToFile($"AutoUpdate | 优先通过GitHub Releases API检测..."); // 1. 优先通过GitHub Releases API获取 - var (apiVersion, apiDownloadUrl, apiReleaseNotes) = await GetLatestGithubRelease(channel); - if (!string.IsNullOrEmpty(apiVersion) && !string.IsNullOrEmpty(apiDownloadUrl)) + var (apiVersion, _, apiReleaseNotes) = await GetLatestGithubRelease(channel); + if (!string.IsNullOrEmpty(apiVersion)) { Version local = new Version(localVersion); Version remote = new Version(apiVersion.TrimStart('v', 'V')); if (remote > local || alwaysGetRemote) { LogHelper.WriteLogToFile($"AutoUpdate | 通过GitHub Releases API发现新版本: {apiVersion}"); - // 用一个虚拟的UpdateLineGroup表示API直链 - var apiGroup = new UpdateLineGroup - { - GroupName = "GitHub Releases API", - VersionUrl = "", - DownloadUrlFormat = apiDownloadUrl, - LogUrl = "" - }; - return (apiVersion, apiGroup, apiReleaseNotes, apiDownloadUrl); + // 只返回版本号和日志,不返回直链 + var group = (await GetAvailableLineGroupsOrdered(channel)).FirstOrDefault(); + return (apiVersion, group, apiReleaseNotes); } else { LogHelper.WriteLogToFile($"AutoUpdate | 当前版本已是最新 (GitHub Releases API)"); - return (null, null, apiReleaseNotes, null); + var group = (await GetAvailableLineGroupsOrdered(channel)).FirstOrDefault(); + return (null, group, apiReleaseNotes); } } // 2. 回退到原有txt方案 @@ -409,7 +405,7 @@ namespace Ink_Canvas.Helpers if (availableGroups.Count == 0) { LogHelper.WriteLogToFile("AutoUpdate | 所有线路组均不可用", LogHelper.LogType.Error); - return (null, null, null, null); + return (null, null, null); } foreach (var group in availableGroups) { @@ -423,12 +419,12 @@ namespace Ink_Canvas.Helpers if (remote > local || alwaysGetRemote) { LogHelper.WriteLogToFile($"AutoUpdate | 发现新版本或强制获取: {remoteVersion}"); - return (remoteVersion, group, null, null); + return (remoteVersion, group, null); } else { LogHelper.WriteLogToFile($"AutoUpdate | 当前版本已是最新"); - return (null, group, null, null); + return (null, group, null); } } else @@ -437,12 +433,12 @@ namespace Ink_Canvas.Helpers } } LogHelper.WriteLogToFile("AutoUpdate | 所有线路组均无法获取版本信息", LogHelper.LogType.Error); - return (null, null, null, null); + return (null, null, null); } catch (Exception ex) { LogHelper.WriteLogToFile($"AutoUpdate | CheckForUpdates错误: {ex.Message}", LogHelper.LogType.Error); - return (null, null, null, null); + return (null, null, null); } } @@ -453,7 +449,7 @@ namespace Ink_Canvas.Helpers } // 使用多线路组下载新版(支持自动切换) - public static async Task DownloadSetupFileWithFallback(string version, List groups) + public static async Task DownloadSetupFileWithFallback(string version, List groups, Action progressCallback = null) { try { @@ -462,6 +458,7 @@ namespace Ink_Canvas.Helpers if (File.Exists(statusFilePath) && File.ReadAllText(statusFilePath).Trim().ToLower() == "true") { LogHelper.WriteLogToFile("AutoUpdate | 安装包已下载"); + progressCallback?.Invoke(100, "已下载完成"); return true; } @@ -482,13 +479,14 @@ namespace Ink_Canvas.Helpers { string url = string.Format(group.DownloadUrlFormat, version); LogHelper.WriteLogToFile($"AutoUpdate | 尝试从线路组 {group.GroupName} 下载: {url}"); - - bool downloadSuccess = await DownloadFile(url, zipFilePath); - + + bool downloadSuccess = await DownloadFile(url, zipFilePath, progressCallback); + if (downloadSuccess) { SaveDownloadStatus(true); LogHelper.WriteLogToFile($"AutoUpdate | 从线路组 {group.GroupName} 下载成功"); + progressCallback?.Invoke(100, "下载完成"); return true; } else @@ -496,8 +494,9 @@ namespace Ink_Canvas.Helpers LogHelper.WriteLogToFile($"AutoUpdate | 线路组 {group.GroupName} 下载失败,尝试下一个线路组", LogHelper.LogType.Warning); } } - + LogHelper.WriteLogToFile("AutoUpdate | 所有线路组下载均失败", LogHelper.LogType.Error); + progressCallback?.Invoke(0, "所有线路组下载均失败"); return false; } catch (Exception ex) @@ -509,13 +508,15 @@ namespace Ink_Canvas.Helpers } SaveDownloadStatus(false); + progressCallback?.Invoke(0, $"下载异常: {ex.Message}"); return false; } } // 下载文件的具体实现 - private static async Task DownloadFile(string fileUrl, string destinationPath) + private static async Task DownloadFile(string fileUrl, string destinationPath, Action progressCallback = null) { + LogHelper.WriteLogToFile($"AutoUpdate | 正在尝试下载: {fileUrl}"); // 检测是否为Windows 7 var osVersion = Environment.OSVersion; bool isWindows7 = osVersion.Version.Major == 6 && osVersion.Version.Minor == 1; @@ -584,10 +585,12 @@ namespace Ink_Canvas.Helpers { double percentage = (double)totalBytesRead / totalBytes.Value * 100; LogHelper.WriteLogToFile($"AutoUpdate | 下载进度: {percentage:F1}% ({(totalBytesRead / 1024.0 / 1024.0):F2} MB / {(totalBytes.Value / 1024.0 / 1024.0):F2} MB)"); + progressCallback?.Invoke(percentage, $"下载中: {percentage:F1}%"); } else { LogHelper.WriteLogToFile($"AutoUpdate | 已下载: {(totalBytesRead / 1024.0 / 1024.0):F2} MB"); + progressCallback?.Invoke(0, $"已下载: {(totalBytesRead / 1024.0 / 1024.0):F2} MB"); } lastProgressUpdate = DateTime.Now; downloadTimeoutTask = Task.Delay(TimeSpan.FromSeconds(60)); @@ -715,10 +718,12 @@ namespace Ink_Canvas.Helpers { double percentage = (double)totalBytesRead / totalBytes.Value * 100; LogHelper.WriteLogToFile($"AutoUpdate | 下载进度: {percentage:F1}% ({(totalBytesRead / 1024.0 / 1024.0):F2} MB / {(totalBytes.Value / 1024.0 / 1024.0):F2} MB)"); + progressCallback?.Invoke(percentage, $"下载中: {percentage:F1}%"); } else { LogHelper.WriteLogToFile($"AutoUpdate | 已下载: {(totalBytesRead / 1024.0 / 1024.0):F2} MB"); + progressCallback?.Invoke(0, $"已下载: {(totalBytesRead / 1024.0 / 1024.0):F2} MB"); } lastProgressUpdate = DateTime.Now; downloadTimeoutTask = Task.Delay(TimeSpan.FromSeconds(60)); @@ -1113,7 +1118,7 @@ namespace Ink_Canvas.Helpers LogHelper.WriteLogToFile($"AutoUpdate | 开始修复版本,通道: {channel}"); // 获取远程版本号(自动选择最快线路组,始终下载远程版本) - var (remoteVersion, group, _, _) = await CheckForUpdates(channel, true); + var (remoteVersion, group, _) = await CheckForUpdates(channel, true); if (string.IsNullOrEmpty(remoteVersion) || group == null) { LogHelper.WriteLogToFile("AutoUpdate | 修复版本时获取远程版本失败", LogHelper.LogType.Error); diff --git a/Ink Canvas/MainWindow.xaml.cs b/Ink Canvas/MainWindow.xaml.cs index 58268965..eae06189 100644 --- a/Ink Canvas/MainWindow.xaml.cs +++ b/Ink Canvas/MainWindow.xaml.cs @@ -552,7 +552,7 @@ namespace Ink_Canvas { AvailableLatestLineGroup = null; // 使用当前选择的更新通道检查更新 - var (remoteVersion, lineGroup, apiReleaseNotes, directDownloadUrl) = await AutoUpdateHelper.CheckForUpdates(Settings.Startup.UpdateChannel); + var (remoteVersion, lineGroup, apiReleaseNotes) = await AutoUpdateHelper.CheckForUpdates(Settings.Startup.UpdateChannel); AvailableLatestVersion = remoteVersion; AvailableLatestLineGroup = lineGroup; diff --git a/Ink Canvas/Windows/HasNewUpdateWindow.xaml.cs b/Ink Canvas/Windows/HasNewUpdateWindow.xaml.cs index 36a1b1d6..07c5a941 100644 --- a/Ink Canvas/Windows/HasNewUpdateWindow.xaml.cs +++ b/Ink Canvas/Windows/HasNewUpdateWindow.xaml.cs @@ -142,11 +142,19 @@ namespace Ink_Canvas DownloadProgressBar.Value = 0; DownloadProgressText.Text = "正在准备下载..."; - // 启动下载 + // 启动多线路下载 bool downloadSuccess = false; try { - downloadSuccess = await DownloadUpdateAsync(); + // 获取当前通道的所有线路组 + var groups = AutoUpdateHelper.ChannelLineGroups[MainWindow.Settings.Startup.UpdateChannel]; + downloadSuccess = await AutoUpdateHelper.DownloadSetupFileWithFallback(NewVersion, groups, (percent, text) => + { + Dispatcher.Invoke(() => { + DownloadProgressBar.Value = percent; + DownloadProgressText.Text = text; + }); + }); } catch (Exception ex) { @@ -311,84 +319,5 @@ namespace Ink_Canvas } } } - - // 下载更新并实时更新进度条(支持断点续传) - private async Task DownloadUpdateAsync() - { - string version = NewVersion; - string updatesFolderPath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "AutoUpdate"); - if (!Directory.Exists(updatesFolderPath)) - Directory.CreateDirectory(updatesFolderPath); - string zipFilePath = Path.Combine(updatesFolderPath, $"InkCanvasForClass.CE.{version}.zip"); - string tmpFilePath = zipFilePath + ".tmp"; - - // 获取下载链接(此处假设主程序已将下载直链传入,或可通过AutoUpdateHelper获取) - string downloadUrl = null; - if (App.Current.Properties.Contains("UpdateDirectDownloadUrl")) - downloadUrl = App.Current.Properties["UpdateDirectDownloadUrl"] as string; - if (string.IsNullOrEmpty(downloadUrl)) - { - // 兜底:用GitHub主线格式 - downloadUrl = $"https://github.com/InkCanvasForClass/community/releases/download/{version}/InkCanvasForClass.CE.{version}.zip"; - } - - long existingLength = 0; - if (File.Exists(tmpFilePath)) - existingLength = new FileInfo(tmpFilePath).Length; - - try - { - using (var client = new System.Net.Http.HttpClient()) - { - client.Timeout = System.TimeSpan.FromMinutes(10); - client.DefaultRequestHeaders.Add("User-Agent", "ICC-CE Auto Updater"); - if (existingLength > 0) - client.DefaultRequestHeaders.Range = new System.Net.Http.Headers.RangeHeaderValue(existingLength, null); - - using (var response = await client.GetAsync(downloadUrl, System.Net.Http.HttpCompletionOption.ResponseHeadersRead)) - { - response.EnsureSuccessStatusCode(); - var totalBytes = response.Content.Headers.ContentLength.HasValue - ? response.Content.Headers.ContentLength.Value + existingLength - : -1L; - - using (var stream = await response.Content.ReadAsStreamAsync()) - using (var fs = new FileStream(tmpFilePath, FileMode.Append, FileAccess.Write, FileShare.None)) - { - byte[] buffer = new byte[8192]; - long totalRead = existingLength; - int read; - var lastUpdate = DateTime.Now; - while ((read = await stream.ReadAsync(buffer, 0, buffer.Length)) > 0) - { - await fs.WriteAsync(buffer, 0, read); - totalRead += read; - if ((DateTime.Now - lastUpdate).TotalMilliseconds > 200) - { - int percent = totalBytes > 0 ? (int)(totalRead * 100 / totalBytes) : 0; - DownloadProgressBar.Value = percent; - DownloadProgressText.Text = totalBytes > 0 - ? $"已下载 {totalRead / 1024 / 1024.0:F2} MB / {totalBytes / 1024 / 1024.0:F2} MB ({percent}%)" - : $"已下载 {totalRead / 1024 / 1024.0:F2} MB"; - lastUpdate = DateTime.Now; - } - } - DownloadProgressBar.Value = 100; - DownloadProgressText.Text = "下载完成,正在校验..."; - await fs.FlushAsync(); - } - if (File.Exists(zipFilePath)) File.Delete(zipFilePath); - File.Move(tmpFilePath, zipFilePath); - return true; - } - } - } - catch (Exception ex) - { - LogHelper.WriteLogToFile($"AutoUpdate | 断点续传下载失败: {ex.Message}", LogHelper.LogType.Error); - // 不删除 .tmp 文件,便于下次断点续传 - return false; - } - } } }