using Shared.Common; using System; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; using System.Net; using System.Text; namespace Shared.Phone.UserCenter { /// /// 备份业务的逻辑 /// public class HdlBackupLogic { #region ■ 变量声明___________________________ /// /// 备份业务的逻辑 /// private static HdlBackupLogic m_Current = null; /// /// 备份业务的逻辑 /// public static HdlBackupLogic Current { get { if (m_Current == null) { m_Current = new HdlBackupLogic(); } return m_Current; } } #endregion #region ■ 获取备份名字列表___________________ /// /// 从云端获取备份数据的名字列表 /// /// 0:App手动备份 1: App 自动备份 2:网关手动备份 3:网关自动备份 /// 网关的唯一Id,获取网关备份需要 /// 是否获取功能备份 /// public List GetBackupListNameFromDB(int ZigbeeBackupType = 0, string ZigbeeUniqueId = null, bool getOptionBackup = false) { //备份名字很少的内存,可以直接一次性全部取完 var pra = new GetBackupListPra(); pra.BackupType = ZigbeeBackupType; pra.GatewayUniqueId = ZigbeeUniqueId; pra.PageSetting.Page = 1; pra.PageSetting.PageSize = 99999; //获取控制主人账号的Token pra.LoginAccessToken = UserCenterLogic.GetConnectMainToken(); //访问接口 string result = UserCenterLogic.GetResponseDataByRequestHttps("App/GetHomeDataBackupPagger", true, pra); if (string.IsNullOrEmpty(result) == true) { return null; } var data = Newtonsoft.Json.JsonConvert.DeserializeObject(result); var list = new List(); foreach (var data2 in data.PageData) { if (ZigbeeUniqueId != null && data2.GatewayUniqueId != ZigbeeUniqueId) { continue; } if (getOptionBackup == false && data2.BackupName == DirNameResourse.OptionBackupName) { //不获取功能备份 continue; } list.Add(data2); } return list; } /// /// 从云端获取备份的文件,然后存入本地指定的临时文件夹 /// 返回文件夹名字(里面存放着全部的文件),返回null时,代表失败 /// /// BackupClassId /// 当前获取是否为网关自动备份 /// ZigbeeUniqueId 网关的唯一Id(当IsGatewayBackup=true时,此参数必须提供 /// public string GetBackFileFromDBAndSetToLocation(string BackupClassId, bool IsGatewayAutoBackup = false, string ZigbeeUniqueId = null) { //不允许按系统的返回键 Shared.Common.CommonPage.BackKeyCanClick = false; UserCenterResourse.AccountOption.AppCanSignout = false; //首先先创建一个临时文件夹,存在文件则清空 string newDir = System.IO.Path.Combine(DirNameResourse.LocalMemoryDirectory, DirNameResourse.DownLoadBackupTempDirectory); Global.CreateEmptyDirectory(newDir, true); //获取这个备份下面有多少个文件 List listFile = GetBackFileIDFromDB(BackupClassId, IsGatewayAutoBackup, ZigbeeUniqueId); if (listFile == null) { //关闭进度条 ProgressFormBar.Current.Close(); //允许按系统的返回键 Shared.Common.CommonPage.BackKeyCanClick = true; UserCenterResourse.AccountOption.AppCanSignout = true; return null; } var pra = new LoadBackInfoPra(); pra.BackupClassId = BackupClassId; pra.IsGatewayAutoBackup = IsGatewayAutoBackup; pra.GatewayUniqueId = ZigbeeUniqueId; //获取控制主人账号的Token pra.LoginAccessToken = UserCenterLogic.GetConnectMainToken(); //一个个的下载文件 int listFileCount = listFile.Count; for (int i = 0; i < listFile.Count; i++) { string fileName = listFile[i]; //账号已经退出 if (HdlCheckLogic.Current.IsAccountLoginOut() == true) { //关闭进度条 ProgressFormBar.Current.Close(); //允许按系统的返回键 Shared.Common.CommonPage.BackKeyCanClick = true; UserCenterResourse.AccountOption.AppCanSignout = true; return null; } //★设置需要获取的文件名字★ pra.BackupFileName = fileName; var result = UserCenterLogic.GetByteResponseDataByRequestHttps("App/DownloadSomeDataBackup", true, pra, null, true); if (result == null) { //关闭进度条 ProgressFormBar.Current.Close(); //允许按系统的返回键 Shared.Common.CommonPage.BackKeyCanClick = true; UserCenterResourse.AccountOption.AppCanSignout = true; return null; } //将输入写入本地的临时文件夹 Global.WriteFileToDirectoryByBytes(newDir, fileName, result); //设置进度值 ProgressFormBar.Current.SetValue(i + 1, listFileCount); } //关闭进度条 ProgressFormBar.Current.Close(); //允许按系统的返回键 Shared.Common.CommonPage.BackKeyCanClick = true; UserCenterResourse.AccountOption.AppCanSignout = true; return newDir; } /// /// 从云端获取全部的备份文件的名字 /// /// BackupClassId /// 当前获取是否为网关自动备份 /// ZigbeeUniqueId 网关的唯一Id(当IsGatewayBackup=true时,此参数必须提供 /// private List GetBackFileIDFromDB(string BackupClassId, bool IsGatewayAutoBackup, string ZigbeeUniqueId) { var pra = new LoadBackInfoPra(); pra.BackupClassId = BackupClassId; pra.PageSetting.PageSize = 999999; pra.PageSetting.Page = 1; pra.IsGatewayAutoBackup = IsGatewayAutoBackup; pra.GatewayUniqueId = ZigbeeUniqueId; //获取控制主人账号的Token pra.LoginAccessToken = UserCenterLogic.GetConnectMainToken(); //首先先获取云端有什么文件 string result = UserCenterLogic.GetResponseDataByRequestHttps("App/GetHomeDataBackupUploadListPagger", true, pra); if (string.IsNullOrEmpty(result) == true) { return null; } var fileListData = Newtonsoft.Json.JsonConvert.DeserializeObject(result); //获取文件名字 List listFileName = new List(); foreach (LoadBackupFileNameInfo file in fileListData.PageData) { listFileName.Add(file.BackupFileName); } return listFileName; } #endregion #region ■ 创建备份___________________________ /// /// 创建一个备份名字(成功时返回备份的主键ID,失败时返回null) /// /// 备份名字 /// 手动备份类型(0:App手动备份,2:网关手动备份) /// 网关的唯一Id,当ManualBackupType=2时,此值不能为空! /// public string CreatNewBackupNameToDB(string backupName, int ManualBackupType = 0, string ZigbeeUniqueId = null) { var pra = new AddBackUpNamePra(); pra.BackupName = backupName; pra.ManualBackupType = ManualBackupType; pra.GatewayUniqueId = ZigbeeUniqueId; //获取控制主人账号的Token pra.LoginAccessToken = UserCenterLogic.GetConnectMainToken(); var result = UserCenterLogic.GetResponseDataByRequestHttps("App/AddHomeAppGatewayName", true, pra); if (string.IsNullOrEmpty(result) == true) { return null; } var data = Newtonsoft.Json.JsonConvert.DeserializeObject(result); return data.BackupClassId; } #endregion #region ■ 上传备份___________________________ /// /// 上传本地所有文件到云端(函数内部有进度条) /// /// 备份主键ID /// 手动备份类型(0:App手动备份,2:网关手动备份) /// 指定上传的是哪个文件夹的文件(全路径),不指定时,上传的是本地路径下的文件 /// 是否设置显示进度条 /// public bool UpLoadBackupFileToDB(string BackupClassId, int ManualBackupType = 0, string upPath = "", bool showBar = true) { List listAllFile = null; //文件夹的全路径 string fullDir = string.Empty; if (upPath == string.Empty) { //获取本地文件 listAllFile = Global.FileListByHomeId(); fullDir = UserCenterLogic.CombinePath(); } else { listAllFile = HdlAutoBackupLogic.GetFileFromDirectory(upPath); fullDir = upPath; } if (listAllFile.Count == 0) { return true; } //普通文件,可以一次性上传多个的 List listNormalFile = new List(); //图片文件,这个东西很大,需要独立出来 List listPicFile = new List(); foreach (string fileName in listAllFile) { if (fileName.EndsWith(".png") == true) { //图片文件 listPicFile.Add(fileName); continue; } listNormalFile.Add(fileName); } //开启进度条 int listFileCount = listAllFile.Count; if (showBar == true) { //开启进度条 正在上传备份文件 ProgressFormBar.Current.Start(); ProgressFormBar.Current.SetMsg(Language.StringByID(R.MyInternationalizationString.uBackupFileUploading)); } //不允许按系统的返回键 Shared.Common.CommonPage.BackKeyCanClick = false; UserCenterResourse.AccountOption.AppCanSignout = false; //你说为什么这里不分一个函数出来(理论上是分函数出来的) //是因为如果分函数的话,会出现双重异步,导致主线程的进度条的百分比永远定死0% for (int i = 0; i < listNormalFile.Count; i++) { string file = listNormalFile[i]; //账号已经退出 if (HdlCheckLogic.Current.IsAccountLoginOut() == true) { //关闭进度条 ProgressFormBar.Current.Close(); //允许按系统的返回键 Shared.Common.CommonPage.BackKeyCanClick = true; UserCenterResourse.AccountOption.AppCanSignout = true; return false; } //判断是否是应该上传的文件 if (IsNotUpLoadFile(file) == true && upPath == string.Empty) { continue; } //整理数据 var datainfo = new FileInfoData(); datainfo.BackupFileName = file; string fullFileName = System.IO.Path.Combine(fullDir, file); datainfo.BackupFileContent = Shared.IO.FileUtils.ReadFile(fullFileName); var list = new List(); list.Add(datainfo); //执行上传 bool falge = DoUpLoadInfoToDB(BackupClassId, list, ManualBackupType); if (falge == false) { //关闭进度条 ProgressFormBar.Current.Close(); //允许按系统的返回键 Shared.Common.CommonPage.BackKeyCanClick = true; UserCenterResourse.AccountOption.AppCanSignout = true; return false; } //设置进度值 ProgressFormBar.Current.SetValue(i + 1, listFileCount); } for (int i = 0; i < listPicFile.Count; i++) { string file = listPicFile[i]; //账号已经退出 if (HdlCheckLogic.Current.IsAccountLoginOut() == true) { //关闭进度条 ProgressFormBar.Current.Close(); //允许按系统的返回键 Shared.Common.CommonPage.BackKeyCanClick = true; UserCenterResourse.AccountOption.AppCanSignout = true; return false; } var listPic = new List(); listPic.Add(file); //上传本地图片文件到云端 bool result = UpLoadBigBackupFileToDB(fullDir, listPic, BackupClassId, ManualBackupType); if (result == false) { //关闭进度条 ProgressFormBar.Current.Close(); //允许按系统的返回键 Shared.Common.CommonPage.BackKeyCanClick = true; UserCenterResourse.AccountOption.AppCanSignout = true; return false; } //设置进度值 ProgressFormBar.Current.SetValue(i + 1 + listNormalFile.Count, listFileCount); } //进度条关闭 ProgressFormBar.Current.Close(); //允许按系统的返回键 Shared.Common.CommonPage.BackKeyCanClick = true; UserCenterResourse.AccountOption.AppCanSignout = true; return true; } /// /// 执行上传到云端 /// /// 备份主键ID /// 上传的数据 /// 手动备份类型(0:App手动备份,2:网关手动备份) /// private bool DoUpLoadInfoToDB(string BackupClassId, List listData, int ManualBackupType = 0) { var upData = new UpLoadDataPra(); upData.ManualBackupType = ManualBackupType; upData.BackupClassId = BackupClassId; upData.UploadSubFileLists = listData; //获取控制主人账号的Token upData.LoginAccessToken = UserCenterLogic.GetConnectMainToken(); bool falge = UserCenterLogic.GetResultStatuByRequestHttps("App/UploadHomeAppGatewaySubFiles", true, upData, null, true); if (falge == false) { return false; } return true; } /// /// 上传本地图片文件到云端 /// /// 文件夹的全路径 /// 图片文件列表 /// 备份主键ID /// 手动备份类型(0:App手动备份,2:网关手动备份) /// private bool UpLoadBigBackupFileToDB(string fullDir, List listPicFile, string BackupClassId, int ManualBackupType = 0) { foreach (string fileName in listPicFile) { string fullName = System.IO.Path.Combine(fullDir, fileName); NameValueCollection nvc = new NameValueCollection(); nvc.Add("RequestVersion", Common.CommonPage.RequestVersion); nvc.Add("LoginAccessToken", UserCenterLogic.GetConnectMainToken()); nvc.Add("HomeId", Shared.Common.Config.Instance.Home.Id); nvc.Add("BackupClassId", BackupClassId); nvc.Add("ManualBackupType", ManualBackupType.ToString()); nvc.Add("IsOtherAccountCtrl", Common.Config.Instance.Home.IsOthreShare.ToString()); string base64 = GetBase64Text(fullName); nvc.Add("UploadSubFileLists[0].BackupFileName", fileName); nvc.Add("UploadSubFileLists[0].BackupFileContent", base64); bool result = UpLoadBigBackupFileToDB("App/UploadHomeAppGatewaySubFiles", fullName, nvc); if (result == false) { return false; } } return true; } /// /// 上传大文件 /// /// 请求接口 /// 文件名字(含路径) /// /// private bool UpLoadBigBackupFileToDB(string RequestName, string fullFileName, NameValueCollection nvc) { string paramName = "file"; string contentType = "application/octet-stream"; string requestUrl = string.Empty; //启用管理员权限 if (Config.Instance.Home.IsOthreShare == true) { requestUrl = $"{Config.Instance.AdminRequestBaseUrl}/{RequestName}"; } else { requestUrl = $"{CommonPage.RequestHttpsHost}/{RequestName}"; } string boundary = "---------------------------" + DateTime.Now.Ticks.ToString("x"); byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n"); HttpWebRequest wr = (HttpWebRequest)WebRequest.Create(requestUrl); wr.ContentType = "multipart/form-data; boundary=" + boundary; wr.Method = "POST"; wr.KeepAlive = true; wr.Credentials = System.Net.CredentialCache.DefaultCredentials; Stream rs = wr.GetRequestStream(); string formdataTemplate = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}"; foreach (string key in nvc.Keys) { rs.Write(boundarybytes, 0, boundarybytes.Length); string formitem = string.Format(formdataTemplate, key, nvc[key]); byte[] formitembytes = System.Text.Encoding.UTF8.GetBytes(formitem); rs.Write(formitembytes, 0, formitembytes.Length); } rs.Write(boundarybytes, 0, boundarybytes.Length); string headerTemplate = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n"; string header = string.Format(headerTemplate, paramName, fullFileName, contentType); byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(header); rs.Write(headerbytes, 0, headerbytes.Length); FileStream fileStream = new FileStream(fullFileName, FileMode.Open, FileAccess.Read); byte[] buffer = new byte[4096]; int bytesRead = 0; while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) != 0) { rs.Write(buffer, 0, bytesRead); } fileStream.Close(); byte[] trailer = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "--\r\n"); rs.Write(trailer, 0, trailer.Length); rs.Close(); WebResponse wresp = null; try { wresp = wr.GetResponse(); Stream stream2 = wresp.GetResponseStream(); StreamReader reader2 = new StreamReader(stream2); string result = reader2.ReadToEnd(); var data = Newtonsoft.Json.JsonConvert.DeserializeObject(result); return UserCenterLogic.CheckNotEorrorMsg(data, requestUrl); } catch { return false; } finally { if (wresp != null) { wresp.Close(); wresp = null; } wr = null; } } #endregion #region ■ 上传Log备份________________________ /// /// 上传Log备份(隐匿功能) /// /// public bool UpLoadLogBackup() { string upPath = UserCenterLogic.CombinePath(DirNameResourse.LocalMemoryDirectory, DirNameResourse.LogDirectory); if (HdlAutoBackupLogic.GetFileFromDirectory(upPath).Count == 0) { //没有Log文件 return true; } ProgressFormBar.Current.Start(); ProgressFormBar.Current.SetMsg("正在上传Log文件"); //从云端获取数据 var pageData = HdlBackupLogic.Current.GetBackupListNameFromDB(0, null, true); if (pageData == null) { ProgressFormBar.Current.Close(); return false; } string backId = string.Empty; for (int i = 0; i < pageData.Count; i++) { if (pageData[i].BackupName == DirNameResourse.OptionBackupName) { //获取功能备份的ID backId = pageData[i].Id; break; } } if (backId == string.Empty) { //创建新的备份 backId = HdlBackupLogic.Current.CreatNewBackupNameToDB(DirNameResourse.OptionBackupName); if (backId == null) { ProgressFormBar.Current.Close(); return false; } } //上传Log文件 bool result = this.UpLoadBackupFileToDB(backId, 0, upPath, false); if (result == true) { try { var listAllFile = HdlAutoBackupLogic.GetFileFromDirectory(upPath); if (listAllFile.Count > 10) { listAllFile.Sort(); while (listAllFile.Count >= 10) { System.IO.File.Delete(listAllFile[0]); listAllFile.RemoveAt(0); } } } catch { } } ProgressFormBar.Current.Close(); HdlThreadLogic.Current.RunMain(() => { var contr = new ShowMsgControl(ShowMsgType.Tip, "Log上传成功"); contr.Show(); }); return result; } #endregion #region ■ 读取隐匿功能配置___________________ /// /// 读取隐匿功能配置(不要在意返回值) /// /// public bool LoadHideOption() { //先初始化 UserCenterResourse.HideOption = new HideOptionInfo(); if (UserCenterResourse.UserInfo.AuthorityNo != 1 && UserCenterResourse.UserInfo.AuthorityNo != 2) { return true; } //无视错误 IMessageCommon.Current.IgnoreError = true; //从云端获取数据 var pageData = this.GetBackupListNameFromDB(0, null, true); if (pageData == null) { //恢复 IMessageCommon.Current.IgnoreError = false; return false; } string backId = string.Empty; for (int i = 0; i < pageData.Count; i++) { if (pageData[i].BackupName == DirNameResourse.OptionBackupName) { //获取功能备份的ID backId = pageData[i].Id; break; } } if (backId == string.Empty) { //没有功能配置 IMessageCommon.Current.IgnoreError = false; return true; } //获取这个备份下面有多少个文件 List listFile = GetBackFileIDFromDB(backId, false, null); if (listFile == null) { //恢复 IMessageCommon.Current.IgnoreError = false; return false; } if (listFile.Count == 0) { //恢复 IMessageCommon.Current.IgnoreError = false; return true; } //检测 string checkKeys = UserCenterLogic.EncryptPassword(UserCenterResourse.FileEncryptKey, DirNameResourse.ShowOptionMenuFile + UserCenterResourse.UserInfo.Account); if (listFile.Contains(checkKeys) == true) { //显示主页隐藏菜单(Debug用) UserCenterResourse.HideOption.CenterHideMenu = 1; } checkKeys = UserCenterLogic.EncryptPassword(UserCenterResourse.FileEncryptKey, DirNameResourse.DetailedLogFile + UserCenterResourse.UserInfo.Account); if (listFile.Contains(checkKeys) == true) { //出力详细Log(Debug用) UserCenterResourse.HideOption.DetailedLog = 1; } checkKeys = UserCenterLogic.EncryptPassword(UserCenterResourse.FileEncryptKey, DirNameResourse.DeviceHistoryFile + UserCenterResourse.UserInfo.Account); if (listFile.Contains(checkKeys) == true) { //显示设备历史版本(Debug用) UserCenterResourse.HideOption.DeviceHistory = 1; } //恢复 IMessageCommon.Current.IgnoreError = false; return true; } #endregion #region ■ 读取备份___________________________ /// /// 读取APP备份文档(函数内部有进度条) /// /// public bool LoadAppBackupInfo(string BackupClassId) { //打开进度条 正在获取备份文件列表 ProgressFormBar.Current.Start(); ProgressFormBar.Current.SetMsg(Language.StringByID(R.MyInternationalizationString.uBackupFileListGetting)); //从云端获取备份的文件,然后存入本地的临时文件夹 string tempDirectory = GetBackFileFromDBAndSetToLocation(BackupClassId); if (tempDirectory == null) { //关闭进度条 ProgressFormBar.Current.Close(); return false; } //关闭进度条 ProgressFormBar.Current.Close(); //如果读取到的文件完全没有问题,则清理本地的文件 UserCenterLogic.DeleteAllLocationFile(false); //没有错误的话,则移动到当前住宅文件夹下面 Global.MoveDirectoryFileToHomeDirectory(tempDirectory, true); //删除全部的自动备份的本地文件(此函数用于读取自动备份的时候使用) HdlAutoBackupLogic.DeleteAllAutoBackupFile(); //刷新本地缓存 UserCenterLogic.RefreshAllMemory(); return true; } #endregion #region ■ 删除备份___________________________ /// /// 删除云端备份 /// /// 备份的主键 /// public bool DeleteDbBackupData(string BackupClassId) { var Pra = new LoadBackInfoPra(); Pra.BackupClassId = BackupClassId; //获取控制主人账号的Token Pra.LoginAccessToken = UserCenterLogic.GetConnectMainToken(); bool success = UserCenterLogic.GetResultStatuByRequestHttps("App/DelHomeAppGatewayName", true, Pra); return success; } #endregion #region ■ 一般方法___________________________ /// /// 判断是否是应该上传的文件 /// /// /// public bool IsNotUpLoadFile(string file) { if (file == "Config.json") { //不能覆盖Config文件 return true; } return false; } /// /// 将文件转为Base64字符串 /// /// /// private string GetBase64Text(string fileName) { string path = Config.Instance.FullPath; string fullName = System.IO.Path.Combine(path, fileName); FileStream fs = File.OpenRead(fullName); byte[] buff = new byte[fs.Length]; fs.Read(buff, 0, buff.Length); fs.Close(); string base64 = Convert.ToBase64String(buff); return base64; } #endregion } }