diff --git a/MasstransferCommon/Utils/Md5Util.cs b/MasstransferCommon/Utils/Md5Util.cs index 51a1869..6ed879e 100644 --- a/MasstransferCommon/Utils/Md5Util.cs +++ b/MasstransferCommon/Utils/Md5Util.cs @@ -21,4 +21,24 @@ public class Md5Util return hashString.ToString(); } + + /// + /// 计算压缩包md5 + /// + /// + /// + public static string Md5ForZipFile(string filePath) + { + using (var md5 = MD5.Create()) + { + using (var stream = File.OpenRead(filePath)) + { + // 计算文件流的哈希值 + var hash = md5.ComputeHash(stream); + // 将哈希值转换为字符串格式 + var hashString = BitConverter.ToString(hash).Replace("-", string.Empty).ToLowerInvariant(); + return hashString; + } + } + } } \ No newline at end of file diff --git a/MasstransferCommon/obj/Debug/net7.0/MasstransferCommon.AssemblyInfo.cs b/MasstransferCommon/obj/Debug/net7.0/MasstransferCommon.AssemblyInfo.cs index 59b202e..07111d0 100644 --- a/MasstransferCommon/obj/Debug/net7.0/MasstransferCommon.AssemblyInfo.cs +++ b/MasstransferCommon/obj/Debug/net7.0/MasstransferCommon.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("MasstransferCommon")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+a303714a635d3146132582a2408fc8cf76a69947")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+64cf3396835594f835ea904d6fccf95de4bc3e01")] [assembly: System.Reflection.AssemblyProductAttribute("MasstransferCommon")] [assembly: System.Reflection.AssemblyTitleAttribute("MasstransferCommon")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/MasstransferCommon/obj/Debug/net7.0/MasstransferCommon.AssemblyInfoInputs.cache b/MasstransferCommon/obj/Debug/net7.0/MasstransferCommon.AssemblyInfoInputs.cache index 6a21fc7..d71e8ba 100644 --- a/MasstransferCommon/obj/Debug/net7.0/MasstransferCommon.AssemblyInfoInputs.cache +++ b/MasstransferCommon/obj/Debug/net7.0/MasstransferCommon.AssemblyInfoInputs.cache @@ -1 +1 @@ -04161de5d5b7e53625665da3c9aa9d1cc0c406c72bef7aeb16057254b572fd39 +24bba642a13e6757b4f3f31fb043b50bb46d2cbfc99854439c2393c381e11be8 diff --git a/MasstransferExporter.sln b/MasstransferExporter.sln index 4f46ac7..bfee5fe 100644 --- a/MasstransferExporter.sln +++ b/MasstransferExporter.sln @@ -6,6 +6,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MasstransferInfrastructure" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MasstransferCommon", "MasstransferCommon\MasstransferCommon.csproj", "{66C6D73C-BADB-4E28-9C83-E701B019626D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestProject1", "TestProject1\TestProject1.csproj", "{D26C3A44-62AF-4ACC-B454-51E1098C2C86}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -24,5 +26,9 @@ Global {66C6D73C-BADB-4E28-9C83-E701B019626D}.Debug|Any CPU.Build.0 = Debug|Any CPU {66C6D73C-BADB-4E28-9C83-E701B019626D}.Release|Any CPU.ActiveCfg = Release|Any CPU {66C6D73C-BADB-4E28-9C83-E701B019626D}.Release|Any CPU.Build.0 = Release|Any CPU + {D26C3A44-62AF-4ACC-B454-51E1098C2C86}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D26C3A44-62AF-4ACC-B454-51E1098C2C86}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D26C3A44-62AF-4ACC-B454-51E1098C2C86}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D26C3A44-62AF-4ACC-B454-51E1098C2C86}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/MasstransferExporter/OTA/Client/OTAClient.cs b/MasstransferExporter/OTA/Client/OTAClient.cs index 58a0eca..654d6e0 100644 --- a/MasstransferExporter/OTA/Client/OTAClient.cs +++ b/MasstransferExporter/OTA/Client/OTAClient.cs @@ -1,45 +1,11 @@ using System.IO.Compression; -using MasstransferCommon.Model.Constant; -using MasstransferCommunicate.Mqtt; using MasstransferCommon.Utils; -using MasstransferCommunicate.Mqtt.Client; -using MasstransferExporter.OTA.Model; + namespace MasstransferExporter.OTA.Client; public class OTAClient { - /// - /// 订阅OTA更新 - /// - public static async Task ListenOTAUpdateEvent() - { - await MessageQueueHelper.Subscribe(Topics.IssuedOTAPackage, HandleUpdateOTAEvent); - } - - /// - /// 查询OTA更新 - /// - /// - public static async Task QueryOTAUpdate(string result) - { - await MessageQueueHelper.Publish(Topics.QueryOTA, result); - } - - /// - /// OTA更新反馈 - /// - /// - public static async Task OTALicenseUpdateEventFeedback(string resutl) - { - await MessageQueueHelper.Publish(Topics.OTAUpgradeFeedback, resutl); - } - - private static async Task HandleUpdateOTAEvent(string topic, string license) - { - - } - /// /// 备份保存重要文件 /// @@ -47,7 +13,7 @@ public class OTAClient /// 目标地址 /// 保存文件扩展名 /// 保存文件日志 - public void BackupEssentialFiles(string sourceDir, string destinationDir, string[] fileExtension, string logFileDir) + public static void BackupEssentialFiles(string sourceDir, string destinationDir, string[] fileExtension, string logFileDir) { try { @@ -92,7 +58,7 @@ public class OTAClient /// 恢复重要文件 /// /// 重要文件备份日志 - public void RecoverCriticalFiles(string logFileDir) + public static void RecoverCriticalFiles(string logFileDir) { try { @@ -121,7 +87,7 @@ public class OTAClient /// /// 源目录地址 /// 压缩文件保存地址 - public void CompressDirectory(string sourceDir, string zipFilePath) + public static void CompressDirectory(string sourceDir, string zipFilePath) { try { @@ -148,7 +114,7 @@ public class OTAClient /// /// 压缩文件地址 /// 解压目录 - public void ExtractDirectory(string zipFilePath, string extractPath) + public static void ExtractDirectory(string zipFilePath, string extractPath) { try { @@ -170,7 +136,7 @@ public class OTAClient /// 删除目录 /// /// 删除目录地址 - public void DeleteDirectory(string sourceDir) + public static void DeleteDirectory(string sourceDir) { if (Directory.Exists(sourceDir)) { @@ -183,11 +149,28 @@ public class OTAClient /// 删除文件 /// /// 删除文件地址 - public void DeleteFile(string sourceDir) + public static void DeleteFile(string sourceDir) { if (File.Exists(sourceDir)) { File.Delete(sourceDir); } } + + /// + /// 校验安装包 + /// + /// + public static bool CheckMD5(string md5, string file_path) + { + var file_md5 = Md5Util.Md5ForZipFile(file_path); + if (file_md5.Equals(md5)) + { + return true; + } + else + { + return false; + } + } } \ No newline at end of file diff --git a/MasstransferExporter/OTA/Model/OTAResultData.cs b/MasstransferExporter/OTA/Model/OTAResultData.cs new file mode 100644 index 0000000..0420792 --- /dev/null +++ b/MasstransferExporter/OTA/Model/OTAResultData.cs @@ -0,0 +1,12 @@ +namespace MasstransferExporter.OTA.Model; + +public class OTAResultData +{ + public byte Result { get; set; } + + public string Msg { get; set; } + + public string OtaSoftwareVersion { get; set; } + + public string CurrentSoftwareVersion { get; set; } +} \ No newline at end of file diff --git a/MasstransferExporter/OTA/Model/OTAUpdateData.cs b/MasstransferExporter/OTA/Model/OTAUpdateData.cs new file mode 100644 index 0000000..5687d76 --- /dev/null +++ b/MasstransferExporter/OTA/Model/OTAUpdateData.cs @@ -0,0 +1,22 @@ +using Org.BouncyCastle.Utilities; + +namespace MasstransferExporter.OTA.Model; + +public class OTAUpdateData +{ + public byte Type { get; set; } + + public string Url { get; set; } + + public string Version { get; set; } + + public string Module { get; set; } + + public long Size { get; set; } + + public string Checksum { get; set; } + + public string Name { get; set; } + + public string Description { get; set; } +} \ No newline at end of file diff --git a/MasstransferExporter/OTA/Model/UpdateInfo.cs b/MasstransferExporter/OTA/Model/UpdateInfo.cs deleted file mode 100644 index 856af8c..0000000 --- a/MasstransferExporter/OTA/Model/UpdateInfo.cs +++ /dev/null @@ -1,8 +0,0 @@ -namespace MasstransferExporter.OTA.Model; - -public class UpdateInfo -{ - public bool IsUpdateAvailable { get; set; } - public string Version { get; set; } - public string DownloadUrl { get; set; } -} \ No newline at end of file diff --git a/MasstransferExporter/OTA/Service/OTAService.cs b/MasstransferExporter/OTA/Service/OTAService.cs index c35c01c..8a4ddad 100644 --- a/MasstransferExporter/OTA/Service/OTAService.cs +++ b/MasstransferExporter/OTA/Service/OTAService.cs @@ -1,11 +1,13 @@ -using MasstransferExporter.OTA.Client; +using MasstransferCommon.Model.Constant; +using MasstransferCommon.Utils; +using MasstransferCommunicate.Mqtt.Client; +using MasstransferExporter.OTA.Client; +using MasstransferExporter.OTA.Model; namespace MasstransferExporter.OTA.Service; public class OTAService { - private readonly OTAClient _otaClient; - private readonly string _appDir; private readonly string _criticalBackupDir; private readonly string _criticalSourceLogPath; @@ -16,7 +18,6 @@ public class OTAService public OTAService(string appDir, string criticalBackupDir, string criticalSourceLogPath, string[] criticalFileExtension, string previousBackupPath, string updatePackagePath) { - _otaClient = new OTAClient(); _appDir = appDir; _criticalBackupDir = criticalBackupDir; _criticalSourceLogPath = criticalSourceLogPath; @@ -25,11 +26,73 @@ public class OTAService _updatePackagePath = updatePackagePath; } + /// + /// 订阅OTA更新 + /// + public async Task ListenOTAUpdateEvent() + { + await MessageQueueHelper.Subscribe(Topics.IssuedOTAPackage, HandleUpdateOTAEvent); + } /// - /// 更新压缩包 + /// 查询OTA更新 /// - public void Update() + /// + public static async Task QueryOTAUpdate() + { + await MessageQueueHelper.Publish(Topics.QueryOTA, null); + } + + /// + /// OTA更新反馈 + /// + /// + public async Task OTALicenseUpdateEventFeedback(OTAResultData resutl) + { + await MessageQueueHelper.Publish(Topics.OTAUpgradeFeedback, resutl); + } + + /// + /// 处理OTA更新 + /// + /// + /// + private async Task HandleUpdateOTAEvent(string topic, OTAUpdateData otaUpdateData) + { + var type = otaUpdateData.Type; + var url = otaUpdateData.Url; + var version = otaUpdateData.Version; + var module = otaUpdateData.Module; + var size = otaUpdateData.Size; + var checksum = otaUpdateData.Checksum; + var name = otaUpdateData.Name; + var description = otaUpdateData.Description; + + OTAResultData otaResultData = new OTAResultData(); + //下载更新包 + await ApiClient.DownloadFileAsync(url, _updatePackagePath); + + //校验压缩包 + if(!OTAClient.CheckMD5(checksum, _updatePackagePath)) return; + + //kill masstransfer + + //启动更新 + otaResultData.Result = Install() ? (byte)1 : (byte)0; + + //restart masstransfer + + //更新反馈 + otaResultData.OtaSoftwareVersion = version; + otaResultData.CurrentSoftwareVersion = version; //**需要修改为当前版本 + + await OTALicenseUpdateEventFeedback(otaResultData); + } + + /// + /// 安装压缩包 + /// + public bool Install() { try { @@ -37,33 +100,36 @@ public class OTAService initDir(); //备份重要文件 - _otaClient.BackupEssentialFiles(_appDir, _criticalBackupDir, _criticalFileExtension, _criticalSourceLogPath); + OTAClient.BackupEssentialFiles(_appDir, _criticalBackupDir, _criticalFileExtension, _criticalSourceLogPath); //备份旧版本文件 - _otaClient.CompressDirectory(_appDir, _previousBackupPath); + OTAClient.CompressDirectory(_appDir, _previousBackupPath); try { //删除旧版本原文件 - _otaClient.DeleteDirectory(_appDir); + OTAClient.DeleteDirectory(_appDir); //解压更新包 - _otaClient.ExtractDirectory(_updatePackagePath, _appDir); + OTAClient.ExtractDirectory(_updatePackagePath, _appDir); //恢复重要文件 - _otaClient.RecoverCriticalFiles(_criticalSourceLogPath); + OTAClient.RecoverCriticalFiles(_criticalSourceLogPath); //删除旧版本备份文件 - _otaClient.DeleteFile(_previousBackupPath); + OTAClient.DeleteFile(_previousBackupPath); //删除更新包 - _otaClient.DeleteFile(_updatePackagePath); + OTAClient.DeleteFile(_updatePackagePath); + + return true; } catch (Exception ex) { RollBack(); Console.WriteLine($"更新异常,已回滚: {ex.Message}"); + return false; } } catch (Exception ex) @@ -73,8 +139,10 @@ public class OTAService //如果重要文件备份已经产生,则删除 if(Directory.Exists(_criticalBackupDir)) { - _otaClient.DeleteDirectory(_criticalBackupDir); + OTAClient.DeleteDirectory(_criticalBackupDir); } + + return false; } } @@ -104,7 +172,7 @@ public class OTAService { if (Directory.Exists(directory)) { - _otaClient.DeleteDirectory(directory); + OTAClient.DeleteDirectory(directory); } } @@ -112,15 +180,15 @@ public class OTAService { if (File.Exists(file)) { - _otaClient.DeleteFile(file); + OTAClient.DeleteFile(file); } } //恢复旧版本文件 - _otaClient.ExtractDirectory(_previousBackupPath, _appDir); + OTAClient.ExtractDirectory(_previousBackupPath, _appDir); //删除旧版本备份 - _otaClient.DeleteFile(_previousBackupPath); + OTAClient.DeleteFile(_previousBackupPath); } } \ No newline at end of file diff --git a/MasstransferExporter/obj/Debug/net7.0/MasstransferExporter.AssemblyInfo.cs b/MasstransferExporter/obj/Debug/net7.0/MasstransferExporter.AssemblyInfo.cs index 25f5d7e..46876c0 100644 --- a/MasstransferExporter/obj/Debug/net7.0/MasstransferExporter.AssemblyInfo.cs +++ b/MasstransferExporter/obj/Debug/net7.0/MasstransferExporter.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("MasstransferExporter")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+a303714a635d3146132582a2408fc8cf76a69947")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+64cf3396835594f835ea904d6fccf95de4bc3e01")] [assembly: System.Reflection.AssemblyProductAttribute("MasstransferExporter")] [assembly: System.Reflection.AssemblyTitleAttribute("MasstransferExporter")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/MasstransferExporter/obj/Debug/net7.0/MasstransferExporter.AssemblyInfoInputs.cache b/MasstransferExporter/obj/Debug/net7.0/MasstransferExporter.AssemblyInfoInputs.cache index 0990bae..cc70908 100644 --- a/MasstransferExporter/obj/Debug/net7.0/MasstransferExporter.AssemblyInfoInputs.cache +++ b/MasstransferExporter/obj/Debug/net7.0/MasstransferExporter.AssemblyInfoInputs.cache @@ -1 +1 @@ -78895e0730c7e01dfba29760f86535377f37711dd2d831a492fe0a2d3f652707 +afb45cd140781d3740c62e8429421ce27af7c578ce7ca503e1181871f13ddf71 diff --git a/MasstransferInfrastructure/Http/ApiClient.cs b/MasstransferInfrastructure/Http/ApiClient.cs index fe4e2fc..d8606dc 100644 --- a/MasstransferInfrastructure/Http/ApiClient.cs +++ b/MasstransferInfrastructure/Http/ApiClient.cs @@ -68,6 +68,20 @@ public class ApiClient : IDisposable return await response.Content.ReadFromJsonAsync(); } + /// + /// 异步请求下载文件 + /// + /// + /// + public static async Task DownloadFileAsync(string fileUrl, string destinationFilePath) + { + using var response = await Client.GetAsync(fileUrl); + response.EnsureSuccessStatusCode(); + + using var fileStream = new FileStream(destinationFilePath, FileMode.Create, FileAccess.Write, FileShare.None); + await response.Content.CopyToAsync(fileStream); + } + public void Dispose() { Client.Dispose(); diff --git a/TestProject1/TestProject1.csproj b/TestProject1/TestProject1.csproj new file mode 100644 index 0000000..126bdb4 --- /dev/null +++ b/TestProject1/TestProject1.csproj @@ -0,0 +1,28 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + + + + diff --git a/TestProject1/UnitTest1.cs b/TestProject1/UnitTest1.cs new file mode 100644 index 0000000..0f77ab7 --- /dev/null +++ b/TestProject1/UnitTest1.cs @@ -0,0 +1,20 @@ +using MasstransferCommon.Utils; +namespace TestProject1; + +public class Tests +{ + private string file_path = @"C:\Users\wangkaiyi\Downloads\JetBrains2023.1.zip"; + private string b = "5181b067ead5386800c291b70b2c9456"; + [SetUp] + public void Setup() + { + + } + + [Test] + public void Test1() + { + var a = Md5Util.Md5ForZipFile(file_path); + Console.WriteLine(a); + } +} \ No newline at end of file