using LitJson; using Newtonsoft.Json; using SC.XR.Unity; using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Text; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; public class DownloadManager : SingletonMono { /// /// 图片集合 /// private Dictionary m_ImageDic; /// /// 等待下载 /// private List m_WaitDownload; private Dictionary> m_WaitDownloadData; /// /// 正在下载中的数据 /// private List m_Downloading; /// /// 已下载完成的数据 /// private List m_Downloaded; /// /// 下载失败 /// private List m_FiledDownload; /// /// 本地已下载数据 /// //private List m_LocaData; private Dictionary> m_LocaData; /// /// 本地数据记录表存储路径 /// private string m_LocaConfigPath; /// /// 本地数据存储路径 /// private string m_LocaDataPath; public string LocaDataPath { get { return m_LocaDataPath; } private set { m_LocaDataPath = value; } } private Dictionary m_AbObjs; public List GetDownloaded() { return m_Downloaded; } private void Awake() { m_ImageDic = new Dictionary(); m_WaitDownload = new List(); m_WaitDownloadData = new Dictionary>(); m_Downloading = new List(); m_Downloaded = new List(); m_FiledDownload = new List(); m_LocaData = new Dictionary>(); m_AbObjs = new Dictionary(); m_LocaConfigPath = FileManager.CalFilePath(Path.Combine(Application.persistentDataPath, "DataConfig.Json")); LocaDataPath = FileManager.CalFilePath(Application.persistentDataPath + "/MaterialData"); if (!Directory.Exists(LocaDataPath)) { Directory.CreateDirectory(LocaDataPath); } //Debug.Log(LocaDataPath); //Debug.Log(m_LocaConfigPath); ReadLocaData(); } /// /// 读取本地数据 /// private void ReadLocaData() { string str = FileManager.ReadFile(m_LocaConfigPath); foreach (JsonData item in JsonMapper.ToObject(str)) { DownloadData data = new DownloadData(item); if (File.Exists(data.localSavePath)) { if (!m_LocaData.ContainsKey(data.downloadPath)) { List datas = new List(); datas.Add(data); m_LocaData.Add(data.downloadPath, datas); } else { var datas = m_LocaData[data.downloadPath]; bool iscontains = false; for (int i = 0; i < datas.Count; i++) { if (datas[i].localSavePath == data.localSavePath) { iscontains = true; } } if (!iscontains) { datas.Add(data); m_LocaData[data.downloadPath] = datas; } } //if (!m_LocaData.Contains(data)) //{ // m_LocaData.Add(data); //} } } } /// /// 保存本地数据 /// private void SaveLocaData() { string str = "[]"; if (m_LocaData.Count > 0) { JsonData jsonData = new JsonData(); foreach (string key in m_LocaData.Keys) { var data = m_LocaData[key]; for (int i = 0; i < data.Count; i++) { jsonData.Add(data[i].ToJsonData()); } } str = jsonData.ToJson(); Debug.Log("保存本地数据:" + str); } FileManager.WriteFile(str, m_LocaConfigPath); } /// /// 检查是否已经下载了资源 /// public bool CheckDownloadData(DownloadData data) { if (string.IsNullOrWhiteSpace(data.downloadPath)) { return true; } if (m_LocaData.ContainsKey(data.downloadPath)) { var datas = m_LocaData[data.downloadPath]; for (int i = 0; i < datas.Count; i++) { if (datas[i].localSavePath == data.localSavePath) { var loca = datas[i]; if (!File.Exists(data.localSavePath)) { datas.RemoveAt(i); m_LocaData[data.downloadPath] = datas; return false; } else { DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); var locatime = startTime.AddSeconds((double)loca.updateTime); var datatime = startTime.AddSeconds((double)data.updateTime); if (DateTime.Compare(locatime, datatime) >= 0) { //Debug.Log(string.Format("{0}>{1}", locatime, datatime)); return true; } else { datas.RemoveAt(i); m_LocaData[data.downloadPath] = datas; File.Delete(data.localSavePath); return false; } } } } } else { return false; } return false; } public void AddDownloadData(DownloadData data) { if (!m_WaitDownloadData.ContainsKey(data.downloadPath)) { m_WaitDownload.Add(data); List datas = new List(); datas.Add(data); m_WaitDownloadData.Add(data.downloadPath, datas); } else { var datas = m_WaitDownloadData[data.downloadPath]; for (int i = 0; i < datas.Count; i++) { if (datas[i].localSavePath == data.localSavePath) { return; } } m_WaitDownloadData[data.downloadPath].Add(data); m_WaitDownload.Add(data); } //if (!m_WaitDownloadURL.Contains(data.downloadPath)) //{ // m_WaitDownload.Add(data); // m_WaitDownloadURL.Add(data.downloadPath); //} } public void UpdataData() { m_Downloaded.Clear(); StartCoroutine(StarDownload()); Debug.Log(m_WaitDownload.Count + "==================================="); } IEnumerator StarDownload() { var loadUI = (LoadingPanel)UIManager.Instance.GetUI(UINameConfig.LoadingPanel); var count = m_WaitDownload.Count; yield return new WaitForSeconds(2f); while (true) { if (m_Downloading.Count < 1 && m_WaitDownload.Count > 0) { var data = m_WaitDownload[0]; m_WaitDownload.RemoveAt(0); if (CheckDownloadData(data)) { m_Downloaded.Add(data); AddLocaData(data); continue; } m_Downloading.Add(data); loadUI.TextStr = data.downloadPath; switch (data.type) { case (int)MaterialType.Image: GetImage(data, (Image)null); //m_Downloading.Remove(data); //m_Downloaded.Add(data); //AddLocaData(data); break; case (int)MaterialType.Video: DownloadFile(data); break; case (int)MaterialType.Model: DownloadFile(data); //GetAssetBundle(data); break; case (int)MaterialType.Vuforia: DownloadFile(data); break; default: break; } } //yield return new WaitForSeconds(1f); if (m_Downloading.Count <= 0 && m_Downloaded.Count + m_FiledDownload.Count == count) { SaveLocaData(); loadUI.ProgressStr = ""; UIManager.Instance.ShowUI(UINameConfig.LoadingPanel, typeof(LoadingPanel), (int)ELoadState.updateEnd); yield break; } loadUI.ProgressStr = ((float)(m_Downloaded.Count + m_FiledDownload.Count) / count).ToString("P"); yield return null; } } #region public 请求方法 /// /// 获取图片 /// /// 图片地址 /// 图片类型 public void GetImage(DownloadData data, Image image) { if (string.IsNullOrEmpty(data.downloadPath)) { m_Downloading.Remove(data); m_FiledDownload.Add(data); return; } StartCoroutine(LoadImage(data, (tex) => { if(tex) { Sprite sprite = Sprite.Create(tex, new Rect(0, 0, tex.width, tex.height), new Vector2(0.5f, 0.5f)); if (image != null) { image.sprite = sprite; image.transform.localScale = new Vector3(1, (float)tex.height / (float)tex.width, 1); } } })); } /// /// 获取图片 /// /// 图片地址 /// 图片类型 public void GetImage(DownloadData data, RawImage image) { if (string.IsNullOrEmpty(data.downloadPath)) { image.texture = null; return; } StartCoroutine(LoadImage(data, (tex) => { if (image == null) { return; } image.texture = tex; })); } /// /// 请求服务器地址上的音效 /// /// 没有音效地址 /// 请求发起后处理回调结果的委托,处理请求结果的AudioClip /// 音效类型 /// public void GetAudioClip(string url, Action actionResult, AudioType audioType = AudioType.WAV) { StartCoroutine(DownloadAudioClip(url, actionResult, audioType)); } /// /// 请求AssetBundle /// /// AssetBundle地址 /// 请求发起后处理回调结果的委托,处理请求结果的AssetBundle /// public void GetAssetBundle(DownloadData data, Action actionResult = null) { StartCoroutine(_GetAssetBundle(data, actionResult)); } /// /// 下载文件 /// /// 请求地址 /// 储存文件的路径,路径需包含文件名 /// 请求发起后处理回调结果的委托,处理请求对象 /// public void DownloadFile(DownloadData data, Action actionResult = null) { StartCoroutine(_DownloadFile(data, actionResult)); } #endregion #region 文件 /// /// 下载文件 /// /// 请求地址 /// 储存文件的路径 /// 请求发起后处理回调结果的委托,处理请求对象 /// IEnumerator _DownloadFile(DownloadData data, Action actionResult = null) { string url = HttpAction.baseurl + HttpAction.file_download; FileDown file = new FileDown(); if (string.IsNullOrWhiteSpace(data.downloadPath)) { m_Downloading.Remove(data); m_FiledDownload.Add(data); yield break; } file.url = data.downloadPath; string jsonString = JsonConvert.SerializeObject(file); byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonString); if (File.Exists(data.localSavePath)) { m_Downloading.Remove(data); m_Downloaded.Add(data); AddLocaData(data); //Debug.Log(data.downloadPath + "---------------------------------"); yield break; } Debug.LogFormat("{0}:{1}", "文件下载路径为", url); UnityWebRequest uwr = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST); uwr.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw); uwr.downloadHandler = new DownloadHandlerFile(data.localSavePath); uwr.SetRequestHeader("authorization", UserInfo.Instance.Token); foreach (var v in HttpTool.Instance.RequestHeader) { uwr.SetRequestHeader(v.Key, v.Value); } yield return uwr.SendWebRequest(); while (!uwr.isDone) { Debug.Log(uwr.downloadProgress); } m_Downloading.Remove(data); //Debug.Log(data.downloadPath + "---------------------------------"); if (uwr.isNetworkError || uwr.isHttpError) { Debug.LogErrorFormat("{0}:{1}", "当前下载发生错误", uwr.error); m_FiledDownload.Add(data); } else { AddLocaData(data); m_Downloaded.Add(data); } if (actionResult != null) { actionResult(uwr); } uwr.Abort(); uwr.Dispose(); } #endregion #region 图片下载 public void LoadMap(DownloadData data, Image image, Action loadEnd) { StartCoroutine(LoadImage(data, loadEnd)); } /// /// 加载图片 /// /// /// /// private IEnumerator LoadImage(DownloadData data, Action loadEnd) { Texture2D texture = null; //先从内存加载 if (m_ImageDic.TryGetValue(data.downloadPath, out texture)) { Debug.Log("从内存获取"); //Debug.Log(data.downloadPath + "---------------------------------"); m_Downloading.Remove(data); m_Downloaded.Add(data); AddLocaData(data); loadEnd.Invoke(texture); yield break; } //Debug.Log("下载路径为" + filePath); //从本地加载 bool hasLoad = false; if (File.Exists(data.localSavePath)) yield return DownloadTexture(data, (state, localTexture) => { Debug.Log("从本地获取 " + data.localSavePath); hasLoad = state; if (state) { loadEnd.Invoke(localTexture); if (!m_ImageDic.ContainsKey(data.downloadPath)) { m_ImageDic.Add(data.downloadPath, localTexture); } //Debug.Log(data.downloadPath + "---------------------------------"); m_Downloading.Remove(data); m_Downloaded.Add(data); AddLocaData(data); } }, true); if (hasLoad) yield break; //loaded //下载 yield return DownloadTexture(data, (state, downloadTexture) => { hasLoad = state; if (state) { Debug.Log("网络下载"); loadEnd.Invoke(downloadTexture); if (!m_ImageDic.ContainsKey(data.downloadPath)) m_ImageDic.Add(data.downloadPath, downloadTexture); Save2LocalPath(data.localSavePath, downloadTexture); AddLocaData(data); m_Downloaded.Add(data); } else { m_FiledDownload.Add(data); } m_Downloading.Remove(data); //Debug.Log(data.downloadPath + "---------------------------------"); }, false); } /// /// 下载图片 /// /// /// 下载结果 /// 判断是从网络下载还是从本地加载 /// private IEnumerator DownloadTexture(DownloadData data, Action downloadEnd, bool isLoca) { string realUrl = isLoca ? data.localSavePath : HttpAction.baseurl + data.downloadPath; //Debug.Log("图片下载地址为" + realUrl); //if (isLoca) //{ //string realUrl = data.localSavePath; if (!isLoca && File.Exists(data.localSavePath)) { File.Delete(data.localSavePath); } if (isLoca) { #if UNITY_EDITOR realUrl = data.localSavePath; #elif UNITY_ANDROID realUrl = "file://" + data.localSavePath; #endif } using (UnityWebRequest request = new UnityWebRequest(realUrl)) { DownloadHandlerTexture downloadHandlerTexture = new DownloadHandlerTexture(true); request.downloadHandler = downloadHandlerTexture; yield return request.SendWebRequest(); if (string.IsNullOrEmpty(request.error)) { Texture2D localTexture = downloadHandlerTexture.texture; downloadEnd.Invoke(true, localTexture); Resources.UnloadUnusedAssets(); } else { downloadEnd.Invoke(false, null); if (File.Exists(data.localSavePath)) { File.Delete(data.localSavePath); } Debug.LogError(request.error); Debug.LogError(isLoca); Debug.LogError(realUrl); Debug.LogError(data.localSavePath); Debug.LogError(data.downloadPath); Debug.LogError("图片下载失败"); } request.Abort(); request.downloadHandler.Dispose(); request.Dispose(); } //} //else //{ // string realUrl = HttpTool.Instance.BaseUrl + "/file/download"; // FileDown file = new FileDown(); // file.url = data.downloadPath; // string jsonString = JsonMapper.ToJson(file); // byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonString); // using (UnityWebRequest request = new UnityWebRequest(realUrl, "POST")) // { // request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw); // DownloadHandlerTexture downloadHandlerTexture = new DownloadHandlerTexture(true); // request.downloadHandler = downloadHandlerTexture; // request.SetRequestHeader("authorization", HttpTool.Instance.Token); // foreach (var v in HttpTool.Instance.RequestHeader) // { // request.SetRequestHeader(v.Key, v.Value); // } // yield return request.SendWebRequest(); // if (string.IsNullOrEmpty(request.error)) // { // Texture2D localTexture = downloadHandlerTexture.texture; // downloadEnd.Invoke(true, localTexture); // } // else // { // downloadEnd.Invoke(false, null); // if (File.Exists(data.localSavePath)) // { // File.Delete(data.localSavePath); // } // Debug.Log(request.error); // Debug.Log(data.downloadPath); // Debug.LogError("图片下载失败"); // } // request.Abort(); // request.Dispose(); // } //} } public void GetMapImage(DownloadData data, Image image, Action loadEnd) { StartCoroutine(GetMapImage(data, loadEnd)); } IEnumerator GetMapImage(DownloadData data, Action downloadEnd) { string realUrl = HttpAction.baseurl + HttpAction.file_download; FileDown file = new FileDown(); file.url = data.downloadPath; string jsonString = JsonConvert.SerializeObject(file); byte[] bodyRaw = Encoding.UTF8.GetBytes(jsonString); using (UnityWebRequest request = new UnityWebRequest(realUrl, "POST")) { request.uploadHandler = (UploadHandler)new UploadHandlerRaw(bodyRaw); DownloadHandlerTexture downloadHandlerTexture = new DownloadHandlerTexture(true); request.downloadHandler = downloadHandlerTexture; request.SetRequestHeader("authorization", UserInfo.Instance.Token); foreach (var v in HttpTool.Instance.RequestHeader) { request.SetRequestHeader(v.Key, v.Value); } yield return request.SendWebRequest(); if (string.IsNullOrEmpty(request.error)) { Texture2D localTexture = downloadHandlerTexture.texture; downloadEnd.Invoke(true, localTexture); Resources.UnloadUnusedAssets(); } else { downloadEnd.Invoke(false, null); if (File.Exists(data.localSavePath)) { File.Delete(data.localSavePath); } Debug.LogError(request.error); Debug.LogError(data.downloadPath); Debug.LogError("小地图下载失败"); } request.Abort(); request.downloadHandler.Dispose(); request.Dispose(); } } /// /// 保存图片 /// /// /// private void Save2LocalPath(string path, Texture2D texture) { byte[] bytes = texture.EncodeToPNG(); //string savePath = GetLocalPath(); //string filename = Path.GetFileName(url); if (!Directory.Exists(path)) { DirectoryInfo pathInfo = new DirectoryInfo(path); pathInfo.Parent.Create(); } if (File.Exists(path)) { File.Delete(path); } try { File.WriteAllBytes(path, bytes); } catch (Exception ex) { Debug.LogError(ex.ToString()); } } /// /// 获取图片保存路径 /// 是否加入用户/场景目录 /// /// private string GetLocalPath() { string savePath = LocaDataPath + "/" + DataManager.Instance.CurrentScene.id.ToString() + "/pics/"; if (!Directory.Exists(savePath)) { Directory.CreateDirectory(savePath); } return savePath; } #endregion #region 音效 /// /// 请求服务器地址上的音效 /// /// 音效地址 /// 请求发起后处理回调结果的委托,处理请求结果的AudioClip /// 音效类型 /// IEnumerator DownloadAudioClip(string url, Action actionResult, AudioType audioType = AudioType.WAV) { using (var uwr = UnityWebRequestMultimedia.GetAudioClip(url, audioType)) { yield return uwr.SendWebRequest(); if (!(uwr.isNetworkError || uwr.isHttpError)) { if (actionResult != null) { actionResult(DownloadHandlerAudioClip.GetContent(uwr)); } } } } #endregion #region AssetBundle /// /// 请求AssetBundle /// /// AssetBundle地址 /// 请求发起后处理回调结果的委托,处理请求结果的AssetBundle /// IEnumerator _GetAssetBundle(DownloadData data, Action actionResult = null) { if (string.IsNullOrWhiteSpace(data.downloadPath)) { m_Downloading.Remove(data); m_FiledDownload.Add(data); yield break; } else { if (m_AbObjs.ContainsKey(Util.MD5Encrypt(data.downloadPath))) { m_Downloading.Remove(data); m_Downloaded.Add(data); //Debug.Log(data.downloadPath + "---------------------------------"); yield break; } string baseUrl = HttpAction.baseurl + data.downloadPath; //Debug.Log(baseUrl + "ABABABABABAB"); AssetBundle ab = null; UnityWebRequest request = UnityWebRequestAssetBundle.GetAssetBundle(baseUrl); request.SetRequestHeader("authorization", UserInfo.Instance.Token); yield return request.SendWebRequest(); if (request.isNetworkError || request.isHttpError) { m_Downloading.Remove(data); m_FiledDownload.Add(data); Debug.LogError(request.error); } else { ab = DownloadHandlerAssetBundle.GetContent(request); if (ab == null) { request.Dispose(); yield break; } AssetBundleRequest abrequest = ab.LoadAssetAsync(data.name); yield return abrequest; GameObject obj = abrequest.asset as GameObject; var @object = Instantiate(obj); @object.SetActive(false); m_AbObjs.Add(Util.MD5Encrypt(data.downloadPath), @object); m_Downloading.Remove(data); m_Downloaded.Add(data); AddLocaData(data); ab.Unload(false); } request.Abort(); request.Dispose(); } } #endregion private void AddLocaData(DownloadData data) { if (m_LocaData.ContainsKey(data.downloadPath)) { var datas = m_LocaData[data.downloadPath]; bool iscontains = false; for (int i = 0; i < datas.Count; i++) { if (datas[i].localSavePath == data.localSavePath) { iscontains = true; DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1)); var time1 = startTime.AddSeconds((double)datas[i].updateTime); var time2 = startTime.AddSeconds((double)data.updateTime); if (DateTime.Compare(time1, time2) >= 0) { //Debug.Log(string.Format("{0}>{1}", time1, time2)); return; } else { datas.RemoveAt(i); datas.Add(data); m_LocaData[data.downloadPath] = datas; return; } } } if (!iscontains) { datas.Add(data); m_LocaData[data.downloadPath] = datas; } } else { List datas = new List(); datas.Add(data); m_LocaData.Add(data.downloadPath, datas); } } private void OnApplicationQuit() { Debug.Log("退出程序"); } public GameObject GetAbObj(string DownloadPath) { if (m_AbObjs.ContainsKey(DownloadPath)) { return m_AbObjs[DownloadPath]; } else { return null; } } } public class FileDown { public string url { get; set; } }