namespace Thousandto.Update.Flow { using Thousandto.Update.Data; using Thousandto.Update.Log; using Thousandto.Update.Xml; using System; using System.Collections.Generic; using System.IO; using MD5Utils = UnityEngine.Gonbest.MagicCube.MD5Utils; public class Flow8ExCheckResource : BaseFlow { private int _checkedCount; private DataModel _currentData; private List _forceCheckMd5List; private List _parsedMapDataList; private Dictionary _backDownloadDict; private RepairRecordFileData _repairRecords=null; //本地不存在的文件,需要加入到静默更新列表中 internal List BackDownloadList; //忽略的文件 private static string[] _ignoreFiles = new string[] { "localversion.xml", "filelist.txt", //"thousandtoupdate.bytes", //"ThousandtoBase.bytes", //"ThousandtoCore.bytes", //"ThousandtoDeclare.bytes", //"ThousandtoLogic.bytes", //"ThousandtoSDK.bytes", //"ThousandtoUIForm.bytes", //"ThousandtoUpdate.bytes", //"ThousandtoUpdateForm.bytes", //"Lua.bytes", }; // 必须进行修复检查的资源,这些文件有一个特征,就是通过FileStream读取,并且都不大 private static string[] _needRepairDirs = new string[] { "resources/config/", "resources/mapInfo/" }; //判断是否忽略 private bool IsCheckIgnoreFile(string filePath) { var tmp = filePath.ToLower(); for (int i = 0; i < _ignoreFiles.Length; i++) { if (tmp.IndexOf(_ignoreFiles[i])>=0) { UpdateLog.DEBUG_LOG("忽略文件:" + filePath); return true; } } return false; } //判断必须进行修复检查的文件 private bool IsNeedCheckRepair(string filePath) { var tmp = filePath.ToLower(); for (int i = 0; i < _needRepairDirs.Length; i++) { if (tmp.IndexOf(_needRepairDirs[i]) >= 0) { UpdateLog.DEBUG_LOG("必须进行修复检查的文件:" + filePath); return true; } } return false; } private int checkLocalFile(bool useMd5 = true) { UpdateLog.DEBUG_LOG("检查本地文件md5+++ , useMd5=" + useMd5); _repairRecords.Read(); int count = this._parsedMapDataList.Count; this._checkedCount = 0; int insertSceneIndex = 0; for (int i = 0; i < this._parsedMapDataList.Count; i++) { this._checkedCount++; MapFileData item = this._parsedMapDataList[i]; if (!IsCheckIgnoreFile(item.Name)) { bool needRepair = false; var isBytes = item.Name.EndsWith(".bytes"); if (IsExists(item, useMd5 || isBytes, out needRepair)) { if (needRepair) { RepairList.Add(item); _repairRecords.IncRepairCount(item.Dir + item.Name); //UpdateLog.ERROR_LOG("need repaire: " + item.Dir + item.Name); } } else { string path = BaseFlow._storeDir + "/" + item.Dir + item.Name; _backDownloadDict.Add(path, item); if (item.Dir.IndexOf("/Scene/") > 0) { this.BackDownloadList.Insert(insertSceneIndex++, item); } else { //UpdateLog.ERROR_LOG("back download: " + item.Dir + item.Name); this.BackDownloadList.Add(item); } } } } if (RepairList.Count > 0) { _repairRecords.Write(); } MapFileDataListForDownload = RepairList; UpdateLog.DEBUG_LOG("检查本地文件md5--- ,需要静默下载的文件数:"+ BackDownloadList.Count+";;需要修补的文件数:" + RepairList.Count); return 1; } public override void GetCurDownInfo(out string url, out int total, out int downloaded) { url = ""; total = (this._parsedMapDataList == null) ? 0 : this._parsedMapDataList.Count; downloaded = this._checkedCount; } public bool IsExists(MapFileData item, bool useMd5, out bool needRepair) { needRepair = false; string relativePath = item.Dir + item.Name; string storePath = BaseFlow._storeDir + "/" + relativePath; string inAppPath = BaseFlow._appDir + "/" + relativePath; string existPath = null; //1.首先判断外部目录中是否存在这个文件 //先直接通过拼接路径判断是否存在 if (File.Exists(storePath)) existPath = storePath; //2.判断是否修复 if (!string.IsNullOrEmpty(existPath)) {//2.1 如果外部文件存在,就判断外部文件 //UpdateLog.ERROR_LOG("Updatefile: " + existPath); if(useMd5) needRepair = !CompareFileMd5(existPath, item); else needRepair = !CompareFileSize(existPath, item); return true; } else {//2.2如果外部文件不存在 if (IsNeedCheckRepair(relativePath)) {//2.2.1 处理外部必须存在的文件 needRepair = true; return true; } else {//2.2.2 处理那些包体内存在的文件 string md5 = null; int size = 0; //在尝试读取包内文件配置信息 if (Manager.UpdateManager.Instance.TryGetInAppData(relativePath, out md5, out size)) { //包内文件,直接MD5和size一起比较,因为没有计算消耗 needRepair = (item.Md5 != md5) || (item.FileSize != size); return true; } } } return false; } public MapFileData GetMapFileDataByPath(string path) { MapFileData data = null; string str = Path.GetDirectoryName(path).Replace(@"\", "/") + "/"; string fileName = Path.GetFileName(path); // for (int i = 0; i < this._parsedMapDataList.Count; i++) // { // if (((this._parsedMapDataList[i].Dir != null) && (str.IndexOf(this._parsedMapDataList[i].Dir) >= 0)) && ((fileName != null) && fileName.Equals(this._parsedMapDataList[i].Name, StringComparison.OrdinalIgnoreCase))) // { // data = this._parsedMapDataList[i]; // data.FullPath = path; // return data; // } // } //绝对路径 if (path.IndexOf(_storeDir) == -1) { path = _storeDir + "/" + path; } _backDownloadDict.TryGetValue(path, out data); return data; } public List GetMapListDataToDownload() { return RepairList; } public override void Inititalize() { base.Inititalize(); RepairList = new List(); this._parsedMapDataList = new List(); this.BackDownloadList = new List(); _backDownloadDict = new Dictionary(); } public override void OnEnter(BaseFlow oldFlow) { base.OnEnter(oldFlow); this._currentData = base.CurrentRemoteData; _repairRecords = new RepairRecordFileData(); } private int parseMapFiles() { UpdateLog.DEBUG_LOG("解析map文件+++"); int num = 1; RepairList.Clear(); this.BackDownloadList.Clear(); _backDownloadDict.Clear(); this._parsedMapDataList.Clear(); string resourceUrl = ""; for (int i = 0; i < this._currentData.VersionModelBaseList.Count; i++) { VersionModel model = this._currentData.VersionModelBaseList[i]; string str2 = model.Map_url.Replace(@"\", "/"); string str3 = str2.Substring(str2.LastIndexOf("/") + 1); string mapFile = Path.Combine(BaseFlow._storeDir, str3); resourceUrl = model.ResourceUrl; MapFileManage manage = new MapFileManage(); num = manage.parseMapFile(mapFile, model.ResourceUrl, BaseFlow._storeDir); if (num <= -1) { return num; } this._parsedMapDataList.AddRange(manage.GetMapFileDataList()); } UpdateLog.DEBUG_LOG("解析map文件---"); return num; } public void SetExternalData(List forceCheckList) { this._forceCheckMd5List = forceCheckList; } public override void Uninitialize() { if (RepairList != null) { RepairList.Clear(); } if (this._parsedMapDataList != null) { this._parsedMapDataList.Clear(); } } public override int Work() { if (!base.CheckLastFlowResult()) { return base.LastFlowResult; } int num = this.parseMapFiles(); if (num >= 1) { Recorder.StepRecorder.AddStep(Recorder.StepType.DownloadAndParseMapFile); num = this.checkLocalFile(NeedPatch()); var success = num >= CodeDefine.RET_SUCCESS; Recorder.StepRecorder.AddStep(Recorder.StepType.CheckNeedUpdateFiles, success ? 0: 1, success.ToString()); } else Recorder.StepRecorder.AddStep(Recorder.StepType.DownloadAndParseMapFile, 3, "下载成功但是解析失败"); return num; } //是否有补丁版本升级, 有升级,则需要比对md5 private bool NeedPatch() { string localPathVersion = LocalXml.PatchResVersion; string latestPathVersion = localPathVersion; if (_currentData.LastVersionPatch != null) { latestPathVersion = _currentData.LastVersionPatch.ToVersion; } return CompareVersionFormat(latestPathVersion, localPathVersion) > 0; } private bool CompareFileSize(string sourceFile, MapFileData mapData) { if (!File.Exists(sourceFile)) return false; FileInfo info = new FileInfo(sourceFile); return info.Length == mapData.FileSize; } private bool CompareFileMd5(string sourceFile, MapFileData mapData) { if (!File.Exists(sourceFile)) return false; string md5 = MD5Utils.GetFileMD5(sourceFile); return md5 == mapData.Md5; } } }