Files
PrinceOfGlory/Assets/代码/资源下载/DownloadAssets.cs
kridoo 6e91a0c7f0 111
2025-09-15 17:32:08 +08:00

306 lines
11 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

///////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////断点续存的方式下载网络资源/////////////////////////////////////////
/////////////////////////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;
/// <summary>
/// 存放正在下载资源的UWR事件
/// </summary>
internal Dictionary<string, UnityWebRequest> AssetsUWR = new Dictionary<string, UnityWebRequest>();
/// <summary>
/// 创建新的资源图标
/// </summary>
internal UnityEvent<Assets,string> CreateAssetcell = new UnityEvent<Assets, string>();
/// <summary>
/// 更新资源图标
/// </summary>
internal UnityEvent<Assets, string> UpdateAssetcell = new UnityEvent<Assets, string>();
/// <summary>
/// 删除资源图标
/// </summary>
internal UnityEvent<Assets, string> DeleteAssetcell = new UnityEvent<Assets, string>();
void Awake()
{
if (Instance == null)
Instance = this;
}
/// <summary>
/// 下载资源
/// </summary>
/// <param name="fullUrl">资源url</param>
/// <param name="savePath">本地存放位置</param>
/// <param name="assets">资源信息</param>
/// <param name="isAdded">是否是新增资源</param>
/// <param name="isIcon">是否是封面</param>
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));
}
/// <summary>
/// 断点续存
/// </summary>
/// <param name="fullUrl">资源url</param>
/// <param name="savePath">本地存放位置</param>
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);
}
}
}
/// <summary>
/// 资源是完整的,直接记录下载完成信息
/// </summary>
void DoneRecordInfo(string savePath, Assets assets, bool isIcon)
{
AssetsUWR.Remove(Path.GetFileName(savePath));
if (isIcon)
return;//如果下载的是封面,则不记录
RecordDownloaddoneAssetsinfo(assets);
}
/// <summary>
/// 下载完成记录信息
/// </summary>
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);
}
/// <summary>
/// 记录下载完成的资源信息
/// </summary>
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();
}
}
}