11.资源更新-资源更新删除-获取远端对比文件时不覆盖
11.1 知识点
获取资源服务器中对比文件信息时不要覆盖本地的资源对比文件思路
保存到临时文件中,待AB包下载完成后,在用该临时文件覆盖本地对比文件(当前使用)
压根不保存文件,直接通过下载流读取出字节数组数据转为字符串,待AB包下载完后再保存为本地资源对比文件
修改AB包更新管理器中下载对比文件的名字,先下载到临时文件
// 异步下载资源对比文件的函数,提供回调通知下载完成状态
public async void DownLoadABCompareFile(UnityAction<bool> overCallBack)
{
...
// 本地存储路径,由于多线程不能访问Unity主线程的Application,所以在外面声明
string localPath = Application.persistentDataPath;
// 循环下载,直到下载成功或达到最大重新下载次数
while (!isOver && reDownLoadMaxNum > 0)
{
// 使用异步任务Task.Run在后台线程中执行下载操作
await Task.Run(() =>
{
// 执行下载文件的操作,将下载结果存储在isOver中
isOver = DownLoadFile("ABCompareInfo.txt", localPath + "/ABCompareInfo_TMP.txt");
});
// ...
}
}
// 获取下载下来的AB包中的信息函数
public void GetRemoteABCompareFileInfo()
{
// 读取资源对比文件的内容
string info = File.ReadAllText(Application.persistentDataPath + "/ABCompareInfo_TMP.txt");
// ...
}
11.2 知识点代码
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.Events;
using static ABUpdateMgr;
//AB包更新管理器
public class AssetBundleUpdateManager : BaseSingletonInMonoBehaviour<AssetBundleUpdateManager>
{
//用于存储远端AB包信息的字典 之后 和本地进行对比即可完成 更新 下载相关逻辑
private Dictionary<string, AssetBundleInfo> remoteAssetBundleInfoDictionary = new Dictionary<string, AssetBundleInfo>();
//这个是待下载的AB包列表文件 存储AB包的名字
private List<string> assetBundleDownLoadList = new List<string>();
private bool DownLoadFile(string fileName, string localPath)
{
try
{
//1.创建一个FTP连接 用于下载
FtpWebRequest ftpWebRequest = FtpWebRequest.Create(new Uri("ftp://127.0.0.1/AB/PC/" + fileName)) as FtpWebRequest;
//2.设置一个通信凭证 这样才能下载(如果有匿名账号 可以不设置凭证 但是实际开发中 建议 还是不要设置匿名账号)
NetworkCredential networkCredential = new NetworkCredential("MrTao", "MrTao");
ftpWebRequest.Credentials = networkCredential;
//3.其它设置
// 设置代理为null
ftpWebRequest.Proxy = null;
// 请求完毕后 是否关闭控制连接
ftpWebRequest.KeepAlive = false;
// 操作命令-下载
ftpWebRequest.Method = WebRequestMethods.Ftp.DownloadFile;
// 指定传输的类型 2进制
ftpWebRequest.UseBinary = true;
//4.下载文件
// ftp的流对象
FtpWebResponse ftpWebResponse = ftpWebRequest.GetResponse() as FtpWebResponse;
Stream downLoadStream = ftpWebResponse.GetResponseStream();
using (FileStream fileStream = File.Create(localPath))
{
//一点一点的下载内容
byte[] bytes = new byte[2048];
//返回值 代表读取了多少个字节
int contentLength = downLoadStream.Read(bytes, 0, bytes.Length);
//循环下载数据
while (contentLength != 0)
{
//写入到本地文件流中
fileStream.Write(bytes, 0, contentLength);
//写完再读
contentLength = downLoadStream.Read(bytes, 0, bytes.Length);
}
//循环完毕后 证明下载结束
fileStream.Close();
downLoadStream.Close();
print(fileName + "下载成功");
return true;
}
}
catch (Exception ex)
{
print(fileName + "下载失败" + ex.Message);
return false;
}
}
// 异步下载资源对比文件的函数,提供回调通知下载完成状态
public async void DownLoadABCompareFile(UnityAction<bool> overCallBack)
{
// 打印本地持久化数据路径
print(Application.persistentDataPath);
// 初始化下载是否成功的标志
bool isOver = false;
// 设置重新下载的最大次数
int reDownLoadMaxNum = 5;
// 本地存储路径,由于多线程不能访问Unity主线程的Application,所以在外面声明
string localPath = Application.persistentDataPath;
// 循环下载,直到下载成功或达到最大重新下载次数
while (!isOver && reDownLoadMaxNum > 0)
{
// 使用异步任务Task.Run在后台线程中执行下载操作
await Task.Run(() =>
{
// 执行下载文件的操作,将下载结果存储在isOver中
isOver = DownLoadFile("ABCompareInfo.txt", localPath + "/ABCompareInfo_TMP.txt");
});
// 递减重新下载的次数
--reDownLoadMaxNum;
}
// 通过回调通知外部下载是否完成
overCallBack?.Invoke(isOver);
}
// 获取下载下来的AB包中的信息函数
public void GetRemoteABCompareFileInfo()
{
// 读取资源对比文件的内容
string info = File.ReadAllText(Application.persistentDataPath + "/ABCompareInfo_TMP.txt");
// 使用竖线分割字符串,将每个AB包的信息分离
string[] strs = info.Split('|');
string[] infos = null;
// 遍历每个分割后的AB包信息
for (int i = 0; i < strs.Length; i++)
{
// 使用空格分割每个AB包的详细信息
infos = strs[i].Split(' ');
// 记录每一个远端AB包的信息,之后用于对比
remoteAssetBundleInfoDictionary.Add(infos[0], new AssetBundleInfo(infos[0], infos[1], infos[2]));
}
// 打印信息,表示远端AB包对比文件内容获取结束
print("远端AB包对比文件 内容获取结束");
}
/// <summary>
/// 下载远程AssetBundle文件的函数,异步执行。
/// </summary>
/// <param name="overCallBack">下载完成回调,参数为是否全部下载成功。</param>
/// <param name="updatePro">更新下载进度回调,参数为已下载资源数量和总资源数量。</param>
public async void DownLoadABFile(UnityAction<bool> overCallBack, UnityAction<int, int> updatePro)
{
// 1. 遍历字典的键,根据文件名将AssetBundle包添加到待下载列表中
foreach (string name in remoteAssetBundleInfoDictionary.Keys)
{
// 直接将文件名放入待下载列表中
assetBundleDownLoadList.Add(name);
}
// 本地存储路径,由于多线程不能访问Unity相关内容,因此在外部声明
string localPath = Application.persistentDataPath + "/";
// 是否下载成功的标志
bool isOver = false;
// 下载成功的文件名列表,用于移除下载成功的内容
List<string> tempList = new List<string>();
// 重新下载的最大次数
int reDownLoadMaxNum = 5;
// 下载成功的资源数量
int downLoadOverNum = 0;
// 需要下载的总资源数量
int downLoadMaxNum = assetBundleDownLoadList.Count;
// while循环的目的是进行n次重新下载,避免网络异常时下载失败
while (assetBundleDownLoadList.Count > 0 && reDownLoadMaxNum > 0)
{
for (int i = 0; i < assetBundleDownLoadList.Count; i++)
{
// 通过Task.Run在异步线程中执行下载操作
isOver = false;
await Task.Run(() =>
{
isOver = DownLoadFile(assetBundleDownLoadList[i], localPath + assetBundleDownLoadList[i]);
});
if (isOver)
{
// 2. 更新下载进度,通知外部已下载资源数量和总资源数量
updatePro(++downLoadOverNum, downLoadMaxNum);
tempList.Add(assetBundleDownLoadList[i]); // 下载成功记录下来
}
}
// 将下载成功的文件名从待下载列表中移除
for (int i = 0; i < tempList.Count; i++)
assetBundleDownLoadList.Remove(tempList[i]);
// 递减重新下载的次数
--reDownLoadMaxNum;
}
// 所有内容都下载完毕,通过回调告知外部是否下载完成
overCallBack(assetBundleDownLoadList.Count == 0);
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com