UH3L7——下载AB包
前置知识点
FTP下载相关(Unity网络开发基础中)
C#异步函数
C#Task任务类
目标
在下载完资源对比文件并解析了其中的消息后,根据资源对比文件下载AB包(全部下载,目前不需要对比本地资源来确认哪些AB包文件需要下载)
实现流程
由于下载使用异步执行,因此下载AB包方法DownLoadABFile
是异步方法,需要传入所有AB包下载完毕后要执行的回调函数
Main
脚本的start
方法内传入的下载回调函数内,下载完资源对比文件并解析后
解析完下载好的资源对比文件后,执行ABUpdateManager
的DownLoadABFile
方法,
传入下载好所有AB包要执行的回调函数,和下载好一个AB包后要执行的回调函数
输出AB相关函数执行完毕
ABUpdateManager
的DownLoadABFile
方法内
遍历解析资源对比文件得到的ABInfo
字典remoteInfo
,将所有的AB包文件名字放入到待下载的列表downLoadList
内
声明变量:下载路径,本轮下载是否成功,下载完毕的AB包文件名列表,最多重试下载次数,下载成功次数,本次下载一共要下载的AB包数量
进入循环下载流程,如果待下载列表内还有内容,且还有重试下载次数,就执行下载流程
遍历待下载的列表downLoadList
,根据AB包名字下载文件名
先将本轮下载是否成功赋值为false
,创建Task
任务调用下载方法DownLoadFile
,传入文件名和下载路径
等待执行DownLoadFile
结束,检查下载是否成功,如果成功就执行Main
脚本的start
方法传入的下载好一个AB包后要执行的回调函数
将下载好的AB包文件名添加到下载完毕的AB包文件名列表,回到第5步,开始下一个文件的下载流程
等待所有AB包文件都执行过一遍下载流程了,遍历下载完毕的AB包文件名列表,将下载完毕的AB包从待下载列表downLoadList
移除出去
最多重试下载次数减一,如果待下载列表已被清空,或者重试下载次数归0,则跳出下载循环
执行传入的下载好所有AB包要执行的回调函数,将待下载列表是否已被清空传入进去
Main
脚本的start
方法内传入的下载好所有AB包的回调函数
如果传入false
,则说明下载失败,输出失败信息,如果传入ture
,则说明下载成功,输出成功消息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.SceneManagement;public class Main : MonoBehaviour { void Start () { print(Application.persistentDataPath); ABUpdateManager.Instance.DownLoadABCompareFile((isOver) => { if (isOver) { ABUpdateManager.Instance.GetRemoteABCompareFileInfo(); ABUpdateManager.Instance.DownLoadABFile((isOver) => { if (isOver) { print("所有AB包下载结束,继续处理逻辑" ); } else { print("下载失败,网络出现问题了" ); } }, (nowNum, maxNum) => { Debug.Log($"下载进度:{nowNum} /{maxNum} " ); }); print("AB相关函数执行完毕" ); } else { print("下载失败,网络出现问题了" ); } }); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 using System;using System.Collections.Generic;using System.IO;using System.Net;using System.Threading.Tasks;using UnityEngine;using UnityEngine.Events;public class ABUpdateManager : MonoBehaviour { private static ABUpdateManager instance; public static ABUpdateManager Instance { get { if (instance == null ) { GameObject obj = new GameObject("ABUpdateManager" ); instance = obj.AddComponent<ABUpdateManager>(); } return instance; } } private Dictionary<string , ABInfo> remoteInfo = new Dictionary<string , ABInfo>(); private List<string > downLoadList = new List<string >(); private void OnDestroy () { instance = null ; } public async void DownLoadABCompareFile (UnityAction<bool > overCallBack ) { bool isOver = false ; int reDownloadMaxNum = 5 ; string path = Application.persistentDataPath + "/ABCompareInfo.txt" ; while (!isOver && reDownloadMaxNum > 0 ) { await Task.Run(() => { isOver = DownLoadFile("ABCompareInfo.txt" , path); }); --reDownloadMaxNum; } overCallBack?.Invoke(isOver); } public void GetRemoteABCompareFileInfo () { string info = File.ReadAllText(Application.persistentDataPath + "/ABCompareInfo.txt" ); string [] strs = info.Split('|' ); string [] infos; for (int i = 0 ; i < strs.Length; i++) { infos = strs[i].Split(' ' ); remoteInfo.Add(infos[0 ], new ABInfo(infos[0 ], infos[1 ], infos[2 ])); } Debug.Log("远端AB包对比文件,内容获取结束" ); } public async void DownLoadABFile (UnityAction<bool > overCallBack, UnityAction<int , int > updatePro ) { foreach (string str in remoteInfo.Keys) { downLoadList.Add(str); } string localPath = Application.persistentDataPath + "/" ; bool isOver = false ; List<string > tempList = new List<string >(); int redownLoadMaxNum = 5 ; int downLoadOverNum = 0 ; int downLoadMaxNum = downLoadList.Count; while (downLoadList.Count > 0 && redownLoadMaxNum > 0 ) { for (int i = 0 ; i < downLoadList.Count; i++) { isOver = false ; await Task.Run(() => { isOver = DownLoadFile(downLoadList[i], localPath + downLoadList[i]); }); if (isOver) { updatePro(++downLoadOverNum, downLoadMaxNum); tempList.Add(downLoadList[i]); } } for (int i = 0 ; i < tempList.Count; i++) downLoadList.Remove(tempList[i]); --redownLoadMaxNum; } overCallBack?.Invoke(downLoadList.Count == 0 ); } public bool DownLoadFile (string fileName, string localPath ) { try { FtpWebRequest request = FtpWebRequest.Create(new Uri("ftp://192.168.1.102/AB/PC/" + fileName)) as FtpWebRequest; NetworkCredential credential = new NetworkCredential("MrTang" , "MrTang123" ); request.Credentials = credential; request.Proxy = null ; request.KeepAlive = false ; request.Method = WebRequestMethods.Ftp.DownloadFile; request.UseBinary = true ; FtpWebResponse response = request.GetResponse() as FtpWebResponse; Stream downLoadStream = response.GetResponseStream(); using (FileStream file = File.Create(localPath)) { byte [] bytes = new byte [2048 ]; int contentLength = downLoadStream.Read(bytes, 0 , bytes.Length); while (contentLength > 0 ) { file.Write(bytes, 0 , contentLength); contentLength = downLoadStream.Read(bytes, 0 , bytes.Length); } file.Close(); downLoadStream.Close(); } return true ; } catch (Exception e) { Debug.Log($"{fileName} 下载失败:{e.Message} " ); return false ; } } private class ABInfo { public string name; public long size; public string md5; public ABInfo (string name, string size, string md5 ) { this .name = name; this .size = long .Parse(size); this .md5 = md5; } } }