///////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////断点续存的方式下载网络资源/////////////////////////////////////////
/////////////////////////TODO:UI显示下载进度///暂时使用打印替代(平板不需要)//////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Networking;
public class DownloadAssets : MonoBehaviour
{
public static DownloadAssets Instance;
//五亿字节为一段 0.1G 100mb
double loadedBytes = 100000000;
///
/// 存放正在下载资源的UWR事件
///
internal Dictionary AssetsUWR = new Dictionary();
///
/// 创建新的资源图标
///
internal UnityEvent CreateAssetcell = new UnityEvent();
///
/// 更新资源图标
///
internal UnityEvent UpdateAssetcell = new UnityEvent();
///
/// 删除资源图标
///
internal UnityEvent DeleteAssetcell = new UnityEvent();
void Awake()
{
if (Instance == null)
Instance = this;
}
///
/// 下载资源
///
/// 资源url
/// 本地存放位置
/// 资源信息
/// 是否是新增资源
/// 是否是封面
public void DownLoad(string fullUrl, string savePath, Assets assets, bool isAdded, bool isIcon)
{
//完整的接口
fullUrl = WebNet.DownAssetsUrl + fullUrl;
//Debug.Log(fullUrl);
StartCoroutine(RenewDownLoad(fullUrl, savePath, assets, isAdded, isIcon));
}
///
/// 断点续存
///
/// 资源url
/// 本地存放位置
IEnumerator RenewDownLoad(string fullUrl, string savePath, Assets assets, bool isAdded, bool isIcon)
{
long countLength;
using (UnityWebRequest uwrGetCount = UnityWebRequest.Head(fullUrl))
{
yield return uwrGetCount.SendWebRequest();
//获取资源字节长度
long.TryParse(uwrGetCount.GetResponseHeader("Content-Length"), out countLength);
//Debug.Log($"{savePath}:{countLength}");
}
//long countLength = assets.file_size;
////Debug.LogError(fullUrl);
//if (assets.file_size > 1000000)
//{
// using (UnityWebRequest uwrGetCount = UnityWebRequest.Head(fullUrl))
// {
// yield return uwrGetCount.SendWebRequest();
// //获取资源字节长度
// countLength = long.Parse(uwrGetCount.GetResponseHeader("Content-Length"));
// //Debug.Log($"{savePath}:{countLength}");
// }
//}
using (UnityWebRequest unityWebRequest = UnityWebRequest.Get(fullUrl))
{
//append设置为true文件写入方式为接续写入,不覆盖原文件。
unityWebRequest.downloadHandler = new DownloadHandlerFile(savePath, true);
//创建文件
FileInfo file = new FileInfo(savePath);
string filename = Path.GetFileName(savePath);//资源名字
if (!AssetsUWR.ContainsKey(filename))
AssetsUWR.Add(filename, unityWebRequest);
//当前下载的文件长度
long fileLength = file.Length;
//请求网络数据从第fileLength到最后的字节
unityWebRequest.SetRequestHeader("Range", $"bytes={fileLength}-");//设置Range值
if (!string.IsNullOrEmpty(unityWebRequest.error))
{
Debug.LogError($"下载失败{unityWebRequest.error}");
}
string jsonPath = $"{Path.GetDirectoryName(savePath)}/{assets.resource_name}.json";
//Debug.Log(jsonPath);
double currProgress = 0;
if (fileLength < countLength)
{
unityWebRequest.SendWebRequest();
while (!unityWebRequest.isDone)
{
if (File.Exists(jsonPath))
{
File.Delete(jsonPath);
}
double lastProgress = (double)fileLength / countLength;//上次下载的进度
//Debug.Log($"{savePath}上次下载:{(lastProgress * 100).ToString("0.00")}% ");
double newProgress = unityWebRequest.downloadProgress;
currProgress = lastProgress + newProgress * (1 - lastProgress);
//Debug.Log($"{savePath}已经下载:{(currProgress * 100).ToString("0.00")}% ");
if (savePath.Contains("mp4"))
{
//更新进度条
//UpdateVideoProgressUIEvent.Invoke(filename, currProgress);
}
else if (savePath.Contains("apk"))
{
//更新进度条
//UpdateAppProgressUIEvent.Invoke(filename, currProgress);
}
else
{
//其他资源更新进度条
}
//超过一定的字节关闭现在的协程,开启新的协程,将资源分段下载
if (unityWebRequest.downloadedBytes >= loadedBytes)
{
Coroutine coroutine = StartCoroutine(RenewDownLoad(fullUrl, savePath, assets, isAdded, isIcon));
StopCoroutine(coroutine);
//如果 UnityWebRequest 在进行中,就停止。
unityWebRequest.Abort();
AssetsUWR.Remove(filename);
if (!string.IsNullOrEmpty(unityWebRequest.error))
{
Debug.LogError($"{filename}下载失败:{unityWebRequest.error}");
}
Debug.Log($"开启新的携程继续下载{filename}");
yield return StartCoroutine(RenewDownLoad(fullUrl, savePath, assets, isAdded, isIcon));
}
yield return null;
}
}
else
{
//资源是完整的
DoneRecordInfo(savePath, assets, isIcon);
}
if (unityWebRequest.downloadHandler.isDone)
{
DoneRecordInfo(savePath, assets, isAdded, isIcon);
}
}
}
///
/// 资源是完整的,直接记录下载完成信息
///
void DoneRecordInfo(string savePath, Assets assets, bool isIcon)
{
AssetsUWR.Remove(Path.GetFileName(savePath));
if (isIcon)
return;//如果下载的是封面,则不记录
RecordDownloaddoneAssetsinfo(assets);
}
///
/// 下载完成记录信息
///
void DoneRecordInfo(string savePath, Assets assets, bool isAdded, bool isIcon)
{
AssetsUWR.Remove(Path.GetFileName(savePath));
string extension = Path.GetExtension(savePath).ToLower();
switch (assets.type)//1:apk 2:video 3:image 4:file 5:maps 6:pc应用
{
case 1:
if (isIcon)
{
//Debug.Log($"封面图片:{assets.resource_name}下载完成");
if (isAdded)//资源是新增
{
Debug.Log("创建资源封面");
CreateAssetcell.Invoke(assets, savePath);
}
else//资源是更新
{
Debug.Log("更改资源封面");
UpdateAssetcell.Invoke(assets, savePath);
}
return;
}
else
{
Debug.Log($"app资源:{assets.resource_name}下载完成");
//关闭下载进度条
PicoAPI._Instance.UnInstallApp(assets.brief);
GameTools.Share.Delay(5f, () =>
{
PicoAPI._Instance.InstallApk(savePath);
});
}
break;
case 2:
if (isIcon)
{
//Debug.Log($"封面图片:{assets.resource_name}下载完成");
if (isAdded)//资源是新增
{
Debug.Log("创建资源封面");
CreateAssetcell.Invoke(assets, savePath);
}
else//资源是更新
{
Debug.Log("更改资源封面");
UpdateAssetcell.Invoke(assets, savePath);
}
return;
}
else
{
Debug.Log($"mp4资源:{assets.resource_name}下载完成");
//关闭下载进度条
}
break;
case 3:
Debug.Log($"图片资源:{assets.resource_name}下载完成");
//关闭下载进度条
break;
case 4:
Debug.Log($"文件资源:{assets.resource_name}下载完成");
//关闭下载进度条
break;
case 5:
Debug.Log($"地图资源:{assets.resource_name}下载完成");
//关闭下载进度条
break;
case 6:
if (isIcon)
{
//Debug.Log($"封面图片:{assets.resource_name}下载完成");
if (isAdded)//资源是新增
{
Debug.Log("创建资源封面");
CreateAssetcell.Invoke(assets, savePath);
}
else//资源是更新
{
Debug.Log("更改资源封面");
UpdateAssetcell.Invoke(assets, savePath);
}
return;
}
else
{
Debug.Log($"pc应用资源:{assets.resource_name}下载完成");
//关闭下载进度条
}
break;
default:
//其他未知资源
Debug.Log($"其他资源:{assets.resource_name}下载完成");
break;
}
RecordDownloaddoneAssetsinfo(assets);
}
///
/// 记录下载完成的资源信息
///
public void RecordDownloaddoneAssetsinfo(Assets assets)
{
string json = JsonUtility.ToJson(assets);
byte[] bytes = Encoding.UTF8.GetBytes(json);
string path = $"{Config.AssetsInfoPath}/{assets.resource_name}.json";
GameTools.WriteFile(path, bytes);
}
private void OnDestroy()
{
foreach (var item in AssetsUWR.Values)
{
item.Abort();
}
}
}