From 00ccc313e01251619eefd33d18185acc7000afd8 Mon Sep 17 00:00:00 2001
From: dong <1278815766@qq.com>
Date: Thu, 26 Jun 2025 19:05:42 +0800
Subject: [PATCH] =?UTF-8?q?=E5=8A=A8=E6=80=81=E9=85=8D=E7=BD=AE=E5=B9=B6?=
=?UTF-8?q?=E5=8F=91=E6=95=B0=E9=87=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
App.config | 4 ++
CheckDownload.csproj | 3 +-
Form1.cs | 105 ++++++++++++++++++++++++-------------------
3 files changed, 66 insertions(+), 46 deletions(-)
diff --git a/App.config b/App.config
index ed9893e..0256a61 100644
--- a/App.config
+++ b/App.config
@@ -15,4 +15,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/CheckDownload.csproj b/CheckDownload.csproj
index ec7963b..83348a0 100644
--- a/CheckDownload.csproj
+++ b/CheckDownload.csproj
@@ -125,6 +125,7 @@
+
@@ -176,7 +177,7 @@
- 这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。
+ 这台计算机上缺少此项目引用的 NuGet 程序包。使用"NuGet 程序包还原"可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。
diff --git a/Form1.cs b/Form1.cs
index 0c3250e..e65a45a 100644
--- a/Form1.cs
+++ b/Form1.cs
@@ -22,6 +22,7 @@ using Newtonsoft.Json.Linq;
using System.Collections.Concurrent;
using System.Diagnostics;
+using System.Configuration;
namespace CheckDownload
{
@@ -57,7 +58,9 @@ namespace CheckDownload
// 网络优化: 备用DNS服务列表,提高解析成功率
private static readonly List _dnsServers = new List { "223.5.5.5", "119.29.29.29" };
// 最大并发下载数量
- private static readonly int MaxConcurrentDownloads = 2;
+ private static readonly int MaxConcurrentDownloads = int.TryParse(ConfigurationManager.AppSettings["MaxConcurrentDownloads"], out var mcd) ? mcd : 4;
+ // 最大下载重试次数
+ private static readonly int MaxDownloadRetries = int.TryParse(ConfigurationManager.AppSettings["MaxDownloadRetries"], out var mdr) ? mdr : 2;
// 用于存储下载的文件数据
private Dictionary _downloadedFiles = new Dictionary();
// 已完成的下载数量
@@ -202,17 +205,33 @@ namespace CheckDownload
}
UpdateStatus("下载并验证文件...");
- _totalCount = compareResult.Count;
- await DownloadAndVerifyFiles(compareResult);
- UpdateProgressValue(100);
+ // 根据路径长度排序,优先下载小文件/浅层文件,可加其它排序规则
+ var orderedFileList = compareResult.OrderBy(k => k.Key.Length)
+ .ToDictionary(k => k.Key, v => v.Value);
- // 更新成功后清理临时文件夹
- CleanupTempDirectory();
+ _totalCount = orderedFileList.Count;
+ _completedCount = 0;
+ _downloadedFiles.Clear();
+ var failedFiles = new ConcurrentDictionary();
+
+ await PerformDownloads(orderedFileList, failedFiles);
+
+ if (!failedFiles.IsEmpty)
+ {
+ UpdateStatus($"有 {failedFiles.Count} 个文件下载失败,开始重试...");
+ var stillFailing = await RetryFailedFilesAsync(new Dictionary(failedFiles));
+ if (stillFailing.Any())
+ {
+ UpdateStatus($"重试后仍有 {stillFailing.Count} 个文件下载失败。");
+ }
+ }
+
+ if (_completedCount == 0 && orderedFileList.Count > 0)
+ {
+ throw new Exception("所有文件下载失败。");
+ }
- // 显示更新完成并等待3秒
- UpdateStatus("更新完成");
- await Task.Delay(3000);
- this.Close();
+ await VerifyAndSaveAllFiles();
}
catch (Exception ex)
{
@@ -539,7 +558,7 @@ namespace CheckDownload
UpdateStatus($"使用主域名下载文件...");
- var request = new HttpRequestMessage(HttpMethod.Get, authUrl);
+ var request = new HttpRequestMessage(HttpMethod.Get, authUrl) { Version = HttpVersion.Version11 };
request.Headers.Add("User-Agent", "CheckDownload/1.0");
using (var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead))
@@ -574,7 +593,7 @@ namespace CheckDownload
UpdateStatus($"使用备用域名下载文件...");
- var request = new HttpRequestMessage(HttpMethod.Get, authUrl);
+ var request = new HttpRequestMessage(HttpMethod.Get, authUrl) { Version = HttpVersion.Version11 };
request.Headers.Add("User-Agent", "CheckDownload/1.0");
using (var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead))
@@ -618,7 +637,7 @@ namespace CheckDownload
{
string authUrl = GenerateAuthUrl($"http://{OneDriveMainDomain}{OneDrivePath}", fileName);
- var request = new HttpRequestMessage(HttpMethod.Get, authUrl);
+ var request = new HttpRequestMessage(HttpMethod.Get, authUrl) { Version = HttpVersion.Version11 };
request.Headers.Add("User-Agent", "CheckDownload/1.0");
using (var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead))
@@ -647,7 +666,7 @@ namespace CheckDownload
{
string authUrl = GenerateAuthUrl($"http://{OneDriveBackupDomain}{OneDrivePath}", fileName);
- var request = new HttpRequestMessage(HttpMethod.Get, authUrl);
+ var request = new HttpRequestMessage(HttpMethod.Get, authUrl) { Version = HttpVersion.Version11 };
request.Headers.Add("User-Agent", "CheckDownload/1.0");
using (var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead))
@@ -681,10 +700,9 @@ namespace CheckDownload
/// 重试后仍然失败的文件字典
private async Task> RetryFailedFilesAsync(Dictionary failedFiles)
{
- const int maxRetries = 2;
var filesToRetry = new Dictionary(failedFiles);
- for (int i = 0; i < maxRetries && filesToRetry.Any(); i++)
+ for (int i = 0; i < MaxDownloadRetries && filesToRetry.Any(); i++)
{
UpdateStatus($"第 {i + 1} 次重试,剩余 {filesToRetry.Count} 个文件...");
var failedThisRound = new ConcurrentDictionary();
@@ -693,7 +711,7 @@ namespace CheckDownload
filesToRetry = new Dictionary(failedThisRound);
- if (filesToRetry.Any() && i < maxRetries - 1)
+ if (filesToRetry.Any() && i < MaxDownloadRetries - 1)
{
UpdateStatus($"等待 3 秒后进行下一次重试...");
await Task.Delay(3000);
@@ -715,7 +733,7 @@ namespace CheckDownload
try
{
var requestUri = $"http://{dnsServer}/resolve?name={domain}&type=1&short=1";
- var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
+ var request = new HttpRequestMessage(HttpMethod.Get, requestUri) { Version = HttpVersion.Version11 };
request.Headers.Add("User-Agent", "CheckDownload/1.0");
request.Headers.Host = dnsServer;
@@ -747,31 +765,31 @@ namespace CheckDownload
private async Task VerifyAndSaveAllFiles()
{
UpdateStatus("正在校验文件...");
- var failedFiles = new List();
- var filesForScripting = new List<(string original, string newFile)>();
- int processedCount = 0;
+ var failedFiles = new ConcurrentBag();
+ var filesForScripting = new ConcurrentBag<(string original, string newFile)>();
+
int totalFiles = _downloadedFiles.Count;
+ int completed = 0;
+ var semaphore = new SemaphoreSlim(Environment.ProcessorCount);
- foreach (var item in _downloadedFiles)
+ var tasks = _downloadedFiles.Select(async item =>
{
- string relativePath = item.Key;
- string expectedMd5 = item.Value;
- string tempFilePath = Path.Combine(_tempDirectory, relativePath);
-
+ await semaphore.WaitAsync();
try
{
- processedCount++;
- UpdateStatus($"正在校验和保存文件 ({processedCount}/{totalFiles}): {relativePath}");
+ string relativePath = item.Key;
+ string expectedMd5 = item.Value;
+ string tempFilePath = Path.Combine(_tempDirectory, relativePath);
string actualMd5 = CalculateMD5FromFile(tempFilePath);
if (actualMd5 != expectedMd5.ToLower())
{
- throw new Exception($"MD5校验失败 (期望: {expectedMd5}, 实际: {actualMd5})");
+ failedFiles.Add(relativePath);
+ return;
}
string localPath = Path.Combine(_baseDirectory, relativePath);
string localDir = Path.GetDirectoryName(localPath);
-
if (!Directory.Exists(localDir))
{
Directory.CreateDirectory(localDir);
@@ -782,31 +800,28 @@ namespace CheckDownload
string backupPath = localPath + ".new";
File.Move(tempFilePath, backupPath);
filesForScripting.Add((localPath, backupPath));
- UpdateStatus($"文件 {relativePath} 正在被占用,将在程序重启后更新");
- }
- else
- {
- UpdateStatus($"文件 {relativePath} 已更新");
}
- int percentage = 95 + (int)(processedCount * 5.0 / totalFiles);
- UpdateProgressValue(Math.Min(100, percentage));
}
- catch (Exception ex)
+ finally
{
- UpdateStatus($"文件校验失败: {relativePath} - {ex.Message}");
- failedFiles.Add(relativePath);
+ int done = Interlocked.Increment(ref completed);
+ int percentage = 95 + (int)(done * 5.0 / totalFiles);
+ UpdateProgressValue(Math.Min(100, percentage));
+ semaphore.Release();
}
- }
+ });
+
+ await Task.WhenAll(tasks);
if (filesForScripting.Any())
{
- CreateReplaceScriptForAll(filesForScripting);
+ CreateReplaceScriptForAll(filesForScripting.ToList());
}
- foreach (var failedFile in failedFiles)
+ foreach (var failed in failedFiles)
{
- _downloadedFiles.Remove(failedFile);
+ _downloadedFiles.Remove(failed);
}
if (failedFiles.Count > 0)
@@ -1009,7 +1024,7 @@ namespace CheckDownload
{
var ipUrl = signedUrl.Replace(signedUri.Host, ip);
- var request = new HttpRequestMessage(HttpMethod.Get, ipUrl);
+ var request = new HttpRequestMessage(HttpMethod.Get, ipUrl) { Version = HttpVersion.Version11 };
request.Headers.Host = signedUri.Host;
using (var response = await _httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead))
{