/// <summary> /// 针对.patch_list和.manifest,对所有更新过的补丁资源,进行检验 /// </summary> /// <returns></returns> private bool VerifyPatchResources() { PatchListFile patchList = null; List <string> patchListRemove = null; // 将被从patchList移除的字符串缓存 if (Directory.Exists(_localUpdatePath) && File.Exists(PatchListFilePath) && File.Exists(ManifestFilePath)) { patchList = new PatchListFile(PatchListFilePath); patchListRemove = new List <string>(); var manifestData = new ManifestFile(ManifestFilePath); // var time = Time.time; foreach (var relativePath in patchList.Datas) { var fileName = Path.GetFileName(relativePath); if (fileName.StartsWith(".")) // 忽略.manifest, .resource_version { continue; } // 校验 var fullPath = Path.Combine(this._localUpdatePath, relativePath); if (!manifestData.Datas.ContainsKey(relativePath) && File.Exists(fullPath)) { // 多出来的文件,清理掉 AppendLog("Warn useless `{0}` in .manifest file", relativePath); File.Delete(fullPath); patchListRemove.Add(relativePath); // patch_list存在,但不存在具体文件,证明之前资源包被删掉了 } else { if (!File.Exists(fullPath)) { OnError(this, "Error not found file `{0}`", fullPath); goto Exit0; } var manifestMd5 = manifestData.Datas[relativePath].MD5.ToLower(); var realMd5 = Md5Helper.Md5File(fullPath).ToLower(); if (manifestMd5 != realMd5) { OnError(this, "Error when md5 verify, need: {0}, but: {1}", realMd5, manifestMd5); goto Exit0; } // if (Time.time - time > 0.1f) // 帧速过慢了,回停一下 // { // time = Time.time; // yield return null; // } } } // 搜寻patch_resources目录,确保里面的文件都在.patch_List里! var patchResourcesDirPath = _localUpdatePath; foreach (var filePath in Directory.GetFiles(patchResourcesDirPath, "*", SearchOption.AllDirectories)) { var fileName = Path.GetFileName(filePath); if (fileName.StartsWith(".")) { continue; // 忽略隐藏文件 } var cleanPath = filePath.Substring(patchResourcesDirPath.Length + 1, filePath.Length - patchResourcesDirPath.Length - 1).Replace("\\", "/"); // + - 1为了砍掉/ if (!patchList.Datas.Contains(cleanPath)) { OnError(this, "patch_resources file: {0} not in .patch_list", filePath); goto Exit0; } } } // else 不用处理了, CheckAppValid会做检查 CleanPatchList(patchList, patchListRemove); // verifyResult[0] = true; // yield break; return(true); Exit0: // 验证失败,将清理下载资源。重新走更新流程,会重新下载资源 ClearAllPatchResources(); CleanPatchList(patchList, patchListRemove); // verifyResult[0] = false; return(false); }
protected internal override void Start() { var zipPath = _downloader.GetSavePath(); // 获取压缩文件数量 using (var zipFile = new ZipFile(zipPath)) { TotalDecompressSize = zipFile.Count; DecompressCurrentSize = 0; } using (var s = new ZipInputStream(File.OpenRead(zipPath))) { // 进度条重新来过 //_progressBarCount = 0; //_progressBarCountLastSecond = 0; // 重来 //_progressBarTotalCount = (int)zipJson.Size; // 重新计算进度条 ZipEntry theEntry; //var timeCount = Time.realtimeSinceStartup; try { while ((theEntry = s.GetNextEntry()) != null) { if (theEntry.IsDirectory) { continue; } var cleanPath = theEntry.Name.Replace("\\", "/"); string directorName = Path.Combine(LocalUpdatePath, Path.GetDirectoryName(cleanPath)); var fileName = Path.GetFileName(cleanPath); // 其它解压 string fullFileName = Path.Combine(directorName, fileName); _decompressedList.Add(cleanPath); if (!Directory.Exists(directorName)) { Directory.CreateDirectory(directorName); } if (!String.IsNullOrEmpty(fullFileName)) { using (FileStream streamWriter = File.Create(fullFileName)) { byte[] data = new byte[s.Length]; s.Read(data, 0, data.Length); streamWriter.Write(data, 0, data.Length); DecompressCurrentSize++; AppendLog("解压文件: {0}, 解压的大小: {1}KB", cleanPath, data.Length / 1024f); // 忽略下面的resharper dispose 提示。。。,因为协程里没这问题 //decompressLogs.Add(cleanName); // 记录解压的文件,用于断电续传 } } } if (OnDecompressedEvent != null) { OnDecompressedEvent(this, _decompressedList); } var patchList = new PatchListFile(PatchListPath); if (File.Exists(DeletedFilePath)) { var deleteFile = new DeletedListFile(DeletedFilePath); foreach (var path in deleteFile.Datas) { var fullPath = Path.Combine(LocalUpdatePath, path); if (File.Exists(fullPath)) { File.Delete(fullPath); } else { AppendLog("Not exist file in .deleted file list: {0}", deleteFile); } // remove from patchList patchList.Datas.Remove(path); } // delete the .deleted file File.Delete(DeletedFilePath); } // 解压的文件进行验证 // 进行解压的文件校验 var manifestTable = new ManifestFile(ManifestPath); foreach (var checkPath in _decompressedList) { // .manifest, .delete文件不进行验证 if (checkPath == ManifestFileName) { continue; } if (checkPath == DeletedFileName) { continue; } var checkFullPath = Path.Combine(LocalUpdatePath, checkPath); ManifestFile.Manifest checkMani; if (!manifestTable.Datas.TryGetValue(checkPath, out checkMani)) { throw new Exception(string.Format("Error when check file: {0}, no manifest data", checkPath)); } if (!File.Exists(checkFullPath)) { throw new Exception(string.Format("Error when check file: {0} not exist", checkFullPath)); } var expectMd5 = checkMani; var fileMd5 = Md5Helper.Md5File(checkFullPath); if (expectMd5.MD5.ToLower() != fileMd5.ToLower()) { throw new Exception(string.Format("Error verify on {0}, expect:{1}, but:{2}", checkFullPath, expectMd5.MD5, fileMd5)); } } // 读取、创建.patch_list foreach (var file in _decompressedList) { patchList.Add(file); } patchList.Save(); LocalVersionFile.Write(LocalUpdatePath, ResourceVersionFileName, _downloader.RemoteVersion); } catch (Exception e) { OnError(this, e.Message); } } if (IsDeleteZip) { // 解压完成,对压缩包进行删除 if (File.Exists(zipPath)) { File.Delete(zipPath); } } Finish(); }