diff --git a/Form1.cs b/Form1.cs
index 9b8e80b..82ce4e7 100644
--- a/Form1.cs
+++ b/Form1.cs
@@ -33,6 +33,9 @@ namespace CheckDownload
/// 在线MD5文件名,从DNS查询获取
private string _onlineMd5File = "";
+
+ // 类级别变量,用于存储下载的文件数据
+ private Dictionary _downloadedFiles = new Dictionary();
/// 已完成下载的文件数
private int _completedFiles = 0;
@@ -345,7 +348,9 @@ namespace CheckDownload
/// 下载任务
private async Task DownloadUpdatedFiles(Dictionary differences)
{
- // 设置进度条最大值为需要更新的文件数量
+ // 重置下载状态
+ _completedFiles = 0;
+ _downloadedFiles.Clear();
Update_Pro.Maximum = differences.Count;
Update_Pro.Value = 0;
@@ -361,6 +366,9 @@ namespace CheckDownload
// 等待所有下载任务完成
await Task.WhenAll(downloadTasks);
+
+ // 所有文件下载完成后统一校验和保存
+ VerifyAndSaveAllFiles();
}
///
@@ -371,56 +379,110 @@ namespace CheckDownload
/// 下载任务
private async Task DownloadFileWithSemaphore(KeyValuePair file, SemaphoreSlim semaphore)
{
- // 等待信号量,控制并发数量
await semaphore.WaitAsync();
try
{
- // 下载并验证文件
- await DownloadAndVerifyFile(file.Key, file.Value);
- // 更新进度
- UpdateProgress();
- }
- catch (Exception ex)
- {
- UpdateStatus($"下载失败: {file.Key} - {ex.Message}");
+ await DownloadToMemory(file.Key, file.Value);
}
finally
{
- // 释放信号量,允许其他下载任务执行
semaphore.Release();
}
}
///
- /// 下载并验证文件
+ /// 下载文件到内存并暂存
///
- /// 文件的相对路径
- /// 期望的MD5值
- /// 下载任务
- private async Task DownloadAndVerifyFile(string relativePath, string expectedMd5)
+ private async Task DownloadToMemory(string relativePath, string expectedMd5)
{
- // 更新状态显示当前下载进度
- UpdateStatus($"正在下载 ({Update_Pro.Value + 1}/{Update_Pro.Maximum}): {relativePath}");
-
- // 获取本地路径和临时文件路径
- string localPath = GetLocalPath(relativePath);
- string tempPath = $"{localPath}.tmp";
-
- // 确保目录存在
- EnsureDirectoryExists(localPath);
-
- // 下载文件到临时路径
- using (var client = new WebClient())
+ try
{
- await client.DownloadFileTaskAsync(
- new Uri($"{BaseDownloadUrl}File/{relativePath}"),
- tempPath);
+ // 更新状态显示当前下载进度
+ int current = Interlocked.Increment(ref _completedFiles);
+ UpdateStatus($"正在下载 ({Update_Pro.Value + 1}/{Update_Pro.Maximum}): {expectedMd5}");
+
+ // 下载文件到内存
+ using (var client = new HttpClient())
+ {
+ var fileUrl = $"{BaseDownloadUrl}File/{expectedMd5}";
+ var response = await client.GetAsync(fileUrl);
+ response.EnsureSuccessStatusCode();
+
+ byte[] fileData = await response.Content.ReadAsByteArrayAsync();
+
+ // 存储到内存字典
+ lock (_downloadedFiles)
+ {
+ _downloadedFiles[relativePath] = (fileData, expectedMd5);
+ }
+ }
+
+ // 更新进度
+ UpdateProgress();
+ }
+ catch (Exception ex)
+ {
+ UpdateStatus($"下载失败: {relativePath} - {ex.Message}");
+ throw;
+ }
+ }
+
+ ///
+ /// 校验并保存所有已下载的文件
+ ///
+ private void VerifyAndSaveAllFiles()
+ {
+ UpdateStatus("正在校验文件...");
+
+ // 创建失败文件列表
+ var failedFiles = new List();
+
+ foreach (var item in _downloadedFiles)
+ {
+ string relativePath = item.Key;
+ byte[] data = item.Value.Data;
+ string expectedMd5 = item.Value.ExpectedMd5;
+
+ try
+ {
+ // 计算内存中数据的MD5
+ string actualMd5;
+ using (var md5 = MD5.Create())
+ {
+ byte[] hashBytes = md5.ComputeHash(data);
+ actualMd5 = BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
+ }
+
+ // 校验MD5
+ if (actualMd5 != expectedMd5.ToLower())
+ {
+ throw new Exception($"MD5校验失败 (期望: {expectedMd5}, 实际: {actualMd5})");
+ }
+
+ // 获取本地路径并创建目录
+ string localPath = GetLocalPath(relativePath);
+ EnsureDirectoryExists(localPath);
+
+ // 保存文件
+ File.WriteAllBytes(localPath, data);
+ }
+ catch (Exception ex)
+ {
+ UpdateStatus($"文件校验失败: {relativePath} - {ex.Message}");
+ failedFiles.Add(relativePath);
+ }
}
- // 验证文件MD5
- VerifyFileMd5(tempPath, expectedMd5, relativePath);
- // 替换现有文件
- ReplaceExistingFile(tempPath, localPath);
+ // 清理失败的文件记录
+ foreach (var failedFile in failedFiles)
+ {
+ _downloadedFiles.Remove(failedFile);
+ }
+
+ if (failedFiles.Count > 0)
+ {
+ throw new Exception($"{failedFiles.Count}个文件校验失败");
+ }
}
///