| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266 |
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.IO.Compression;
- using System.Net.Http;
- using System.Text.RegularExpressions;
- using System.Threading.Tasks;
- using Update.Utils;
- namespace Update.Services
- {
- public static class Update
- {
- public delegate void DeleUpdateProgress(string step, int nowP, int maxP);
- public delegate void DeleAfterUpdateProgress(bool ok, string error);
- private static readonly string DEFAULT_DOWNLOAD_PATH = Path.Combine(Environment.CurrentDirectory, "tmp");
- private static readonly List<string> IGNORE_PATHS = new List<string>()
- {
- "update"
- };
- public struct UpdateInfo
- {
- public string MD5 { get; set; }
- public double Version { get; set; }
- }
- public static async Task UpdateApplication(string url, string targetPath, DeleUpdateProgress updateProgress, DeleAfterUpdateProgress afterUpdateProgress, string tmpPath = null)
- {
- await Task.Factory.StartNew(async () =>
- {
- int maxSteps = 7, step = 1;
- if (string.IsNullOrEmpty(tmpPath))
- {
- tmpPath = DEFAULT_DOWNLOAD_PATH;
- }
- string localFile = Path.Combine(tmpPath, Path.GetFileName(url));
- string uncompressPath = Path.Combine(tmpPath, "tmp");
- void clearCache()
- {
- Task.Run(async () => { await ClearCache(uncompressPath, localFile); });
- }
- //await ClearTempPath(uncompressPath);
- updateProgress("获取更新参数", step++, maxSteps);
- UpdateInfo info = await GetUpdateInfo(url);
- if (info.Version < 1 || string.IsNullOrEmpty(info.MD5))
- {
- AfterUpdateProgressEvent(afterUpdateProgress, false, "获取更新参数失败!", clearCache);
- return;
- }
- updateProgress("下载", step++, maxSteps);
- if (!await Download(url, localFile))
- {
- AfterUpdateProgressEvent(afterUpdateProgress, false, "下载失败!", clearCache);
- return;
- }
- updateProgress("校验", step++, maxSteps);
- if (!CheckFileMd5(localFile, info.MD5))
- {
- AfterUpdateProgressEvent(afterUpdateProgress, false, "校验失败!", clearCache);
- return;
- }
- updateProgress("解压", step++, maxSteps);
- if (!await UnCompress(localFile, uncompressPath))
- {
- AfterUpdateProgressEvent(afterUpdateProgress, false, "解压失败!", clearCache);
- return;
- }
- updateProgress("更新", step++, maxSteps);
- if (!await CopyDirectory(uncompressPath, targetPath))
- {
- updateProgress("更新失败", step, maxSteps);
- AfterUpdateProgressEvent(afterUpdateProgress, false, "更新失败!", clearCache);
- return;
- }
- updateProgress("清理缓存", step++, maxSteps);
- if (!await ClearCache(uncompressPath, localFile))
- {
- updateProgress("清理缓存失败", step, maxSteps);
- AfterUpdateProgressEvent(afterUpdateProgress, true, "更新完成,清理缓存失败!", null);
- }
- else
- {
- updateProgress("更新完成", step++, maxSteps);
- AfterUpdateProgressEvent(afterUpdateProgress, true, "更新完成!", null);
- }
- });
- }
- private static void AfterUpdateProgressEvent(DeleAfterUpdateProgress afterUpdateProgress, bool res, string error, Action task)
- {
- afterUpdateProgress.Invoke(res, error);
- task?.Invoke();
- }
- private static async Task<UpdateInfo> GetUpdateInfo(string url)
- {
- UpdateInfo info = new UpdateInfo();
- try
- {
- url = Regex.Replace(url, "\\.[^.]{2,5}$", ".txt", RegexOptions.IgnoreCase);
- HttpResponseMessage response = await Http.Fetch(new Http.Request(url, Http.Method.Get));
- if (response.IsSuccessStatusCode)
- {
- string txt = await response.Content.ReadAsStringAsync();
- info = Utils.Json.Decode<UpdateInfo>(txt);
- }
- }
- catch
- {
- }
- return info;
- }
- private static bool CheckFileMd5(string localFileName, string md5)
- {
- return FileExtensions.FileMd5(localFileName) == md5;
- }
- private static async Task<bool> ClearTempPath(string targetPath)
- {
- try
- {
- await Task.Run(() =>
- {
- DirectoryInfo di = new DirectoryInfo(targetPath);
- if (di.Exists)
- {
- di.Delete(true);
- }
- FileExtensions.CheckDirectory(targetPath, true);
- });
- return true;
- }
- catch
- {
- return false;
- }
- }
- private static async Task<bool> Download(string url, string localFilename)
- {
- try
- {
- HttpResponseMessage response = await Utils.Http.Fetch(new Utils.Http.Request(url, Utils.Http.Method.Get));
- if (response != null && response.IsSuccessStatusCode)
- {
- var bytes = await response.Content.ReadAsByteArrayAsync();
- FileExtensions.WriteBytes(localFilename, bytes);
- }
- return true;
- }
- catch
- {
- return false;
- }
- }
- private static async Task<bool> UnCompress(string localFilename, string targetPath)
- {
- bool r = false;
- try
- {
- r = await Task.Run(async () =>
- {
- bool res = await ClearTempPath(targetPath);
- if (res)
- {
- ZipFile.ExtractToDirectory(localFilename, targetPath);
- res = true;
- }
- return res;
- });
- }
- catch
- {
- }
- return r;
- }
- private static async Task<bool> CopyDirectory(string srcPath, string dstPath)
- {
- bool copyDirectory(string sp, string dp)
- {
- string np;
- try
- {
- DirectoryInfo dir = new DirectoryInfo(sp);
- FileSystemInfo[] fileinfo = dir.GetFileSystemInfos(); //获取目录下(不包含子目录)的文件和子目录
- foreach (FileSystemInfo i in fileinfo)
- {
- np = Path.Combine(dp, i.Name);
- if (i is DirectoryInfo) //判断是否文件夹
- {
- if (!Directory.Exists(np))
- {
- Directory.CreateDirectory(np); //目标目录下不存在此文件夹即创建子文件夹
- }
- if (!IsIgnoreDirectory(i.FullName, srcPath))
- {
- // 判断是否是忽略目录
- copyDirectory(i.FullName, np); //递归调用复制子文件夹
- }
- }
- else
- {
- File.Copy(i.FullName, np, true); //不是文件夹即复制文件,true表示可以覆盖同名文件
- }
- }
- return true;
- }
- catch
- {
- return false;
- }
- }
- return await Task.Run(() => { return copyDirectory(srcPath, dstPath); });
- }
- private static bool IsIgnoreDirectory(string p, string srcRootPath)
- {
- bool res = false;
- Uri a = new Uri(p), b;
- foreach (string s in IGNORE_PATHS)
- {
- b = new Uri(Path.Combine(srcRootPath, s));
- res = a == b;
- if (res)
- {
- break;
- }
- }
- return res;
- }
- private static async Task<bool> ClearCache(string cachePath, string cacheUpdateFile)
- {
- bool res = false;
- await Task.Run(() =>
- {
- try
- {
- DirectoryInfo di = new DirectoryInfo(cachePath);
- if (di.Exists)
- {
- di.Delete(true);
- }
- if (File.Exists(cacheUpdateFile))
- {
- File.Delete(cacheUpdateFile);
- }
- res = true;
- }
- catch { }
- });
- return res;
- }
- }
- }
|