sk-client/Assets/Scripts/Core/ResUpdate/Manager/ResourceDownloadManager.cs

400 lines
12 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using UnityEngine;
using System;
using System.Net;
using System.IO;
using System.Text;
using System.Threading;
using System.Collections;
using System.Collections.Generic;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text.RegularExpressions;
using GameCore;
namespace ResUpdate
{
/// <summary>
/// 下载进度
/// </summary>
public class DownLoadProgress
{
/// <summary>
/// 已经下载的大小Byte
/// </summary>
public long Size
{
get;
private set;
}
/// <summary>
/// 已经下载的大小KB
/// </summary>
public float SizeKB
{
get
{
return 1f * Size / 1024;
}
}
/// <summary>
/// 已经下载的大小MB
/// </summary>
public float SizeMB {
get {
return 1f * Size / 1024/1024;
}
}
/// <summary>
/// 需要下载的大小:Byte
/// </summary>
public long TotalSize
{
get;
private set;
}
/// <summary>
/// 需要下载的大小:KB
/// </summary>
public float TotalSizeKB {
get {
return 1f * TotalSize / 1024;
}
}
/// <summary>
/// 需要下载的大小:MB
/// </summary>
public float TotalSizeMB
{
get {
return 1f * TotalSize / 1024/1024;
}
}
/// <summary>
/// 进度
/// </summary>
public float Progress {
get {
if (TotalSize == 0) return 1f;
return Mathf.Clamp01(1f * Size / TotalSize);
}
}
/// <summary>
/// 下载速度
/// </summary>
public float LoadSpeed
{
get;
private set;
}
/// <summary>
/// 更新进度
/// </summary>
/// <param name="size">已经下载的大小</param>
/// <param name="totalSize">需要下载的大小</param>
internal void UpdateProgress(long size, long totalSize,float speed)
{
this.Size = size;
this.TotalSize = totalSize;
this.LoadSpeed = speed;
}
/// <summary>
/// 重置
/// </summary>
internal void Reset() {
this.Size = 0;
this.TotalSize = 0;
}
}
/// <summary>
/// 资源下载器
/// </summary>
public class ResourceDownloadManager : UnitySingleton<ResourceDownloadManager>
{
/// <summary>
/// 下载更新间隔
/// </summary>
const float DOWNLOAD_UPDATE_INTERVAL = 0.05f;
/// <summary>
/// 下载线程数量
/// </summary>
const int MAX_DOWNLOAD_THREADS_COUNT = 3;
/// <summary>
/// 线程下载器池
/// </summary>
ObjectPool<ThreadDownloader> downloadRequestPool = new ObjectPool<ThreadDownloader>(l=>l.Init(), l => l.Reset());
/// <summary>
/// 线程下载器
/// </summary>
List<ThreadDownloader> downloadRequestList = new List<ThreadDownloader>();
/// <summary>
/// 下载完成的数据
/// </summary>
Dictionary<string, bool> finishedRequest = new Dictionary<string, bool>();
/// <summary>
/// 当前正在下载的数量
/// </summary>
int curDownloadingCount;
/// <summary>
/// 当前网络状态
/// </summary>
NetworkReachability curNetworkStatus = NetworkReachability.NotReachable;
/// <summary>
/// 下载URL
/// </summary>
public string downloadURL
{
get;
set;
}
/// <summary>
/// 是否允许从数据流量下载
/// </summary>
public bool allowDowloadFromWWAN
{
get;
set;
}
void Update()
{
UpdateDownLoadList();
}
/// <summary>
/// 更新下载列表
/// </summary>
void UpdateDownLoadList()
{
if (downloadRequestList.Count == 0)return;
UpdateCurNetworkStatus();
ProcessDownloadList();
}
/// <summary>
/// 处理下载列表
/// </summary>
void ProcessDownloadList()
{
var count = Mathf.Min(MAX_DOWNLOAD_THREADS_COUNT, downloadRequestList.Count);
var i = curDownloadingCount;
for (; i < count; ++i)
{
downloadRequestList[i].Start();
curDownloadingCount++;
}
for (i = 0; i < curDownloadingCount; )
{
var downloadRequest = downloadRequestList[i];
if (downloadRequest.downLoadState == DownloadState.Finished)
{
finishedRequest.Add(downloadRequest.fileName, downloadRequest.isSuccess);
downloadRequestList.RemoveAt(i);
curDownloadingCount--;
downloadRequest.UpdateCallBack();
downloadRequest.FinishCallback();
downloadRequestPool.Release(downloadRequest);
}
else
{
downloadRequest.UpdateCallBack();
++i;
}
}
}
/// <summary>
/// 校验结果
/// </summary>
/// <param name="sender"></param>
/// <param name="certificate"></param>
/// <param name="chain"></param>
/// <param name="errors"></param>
/// <returns></returns>
public static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
{
bool isOk = true;
// If there are errors in the certificate chain,
// look at each error to determine the cause.
if (errors != SslPolicyErrors.None)
{
for (int i = 0; i < chain.ChainStatus.Length; i++)
{
if (chain.ChainStatus[i].Status == X509ChainStatusFlags.RevocationStatusUnknown)
{
continue;
}
chain.ChainPolicy.RevocationFlag = X509RevocationFlag.EntireChain;
chain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
chain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
chain.ChainPolicy.VerificationFlags = X509VerificationFlags.AllFlags;
bool chainIsValid = chain.Build((X509Certificate2)certificate);
if (!chainIsValid)
{
isOk = false;
break;
}
}
}
return isOk;
}
/// <summary>
/// 开始下载文件
/// </summary>
/// <param name="file">文件名</param>
/// <param name="url">下载地址</param>
/// <param name="saveDirectory">保存的文件夹</param>
/// <param name="size">文件大小</param>
/// <param name="crc">文件CRC</param>
/// <param name="finishAction">完成回调</param>
/// <param name="postContent">请求参数</param>
public void StartDownload(string file, string url, string saveDirectory, long size, string crc,Action<string,DownLoadProgress> progressAction=null , Action<string,bool> finishAction = null, string postContent = "")
{
if (FindInDownLoadList(file) != -1)
{
return;
}
if (finishedRequest.ContainsKey(file))
{
if (BaseLogger.isDebug) Debug.Log(string.Format("Re download file: {0}.", file));
finishedRequest.Remove(file);
}
var downloadRequest = downloadRequestPool.Get();
var stringBuilder = new StringBuilder();
var savePath = stringBuilder.Append(UpdateConfigs.PersistentDataPath).Append(saveDirectory).Append(file).ToString();
downloadRequest.Init(file, url, savePath, size, crc,progressAction, finishAction, postContent);
downloadRequestList.Add(downloadRequest);
}
/// <summary>
/// 开始下载文件
/// </summary>
/// <param name="file"></param>
/// <param name="url"></param>
/// <param name="saveDirectory"></param>
/// <param name="finishAction"></param>
/// <param name="postContent"></param>
public void StartDownload(string file, string url, string saveDirectory, Action<string, DownLoadProgress> progressAction = null, Action<string,bool> finishAction = null, string postContent = "")
{
if (FindInDownLoadList(file) != -1)
{
return;
}
if (finishedRequest.ContainsKey(file))
{
if (BaseLogger.isDebug) Debug.Log(string.Format("Re download file: {0}.", file));
finishedRequest.Remove(file);
}
var downloadRequest = downloadRequestPool.Get();
var stringBuilder = new StringBuilder();
var savePath = stringBuilder.Append(UpdateConfigs.PersistentDataPath).Append(saveDirectory).Append(file).ToString();
downloadRequest.Init(file, url, savePath,progressAction,finishAction, postContent);
downloadRequestList.Add(downloadRequest);
}
/// <summary>
/// 是否下载完成
/// </summary>
/// <param name="file">文件名</param>
/// <returns></returns>
public bool IsFinishDownload(string file)
{
return finishedRequest.ContainsKey(file);
}
/// <summary>
/// 是否下载成功
/// </summary>
/// <param name="file">文件名</param>
/// <returns></returns>
public bool IsDownloadSuccess(string file)
{
bool isSuccess = false;
finishedRequest.TryGetValue(file, out isSuccess);
return isSuccess;
}
/// <summary>
/// 是否在下载中
/// </summary>
/// <param name="file">文件名</param>
/// <returns></returns>
public int FindInDownLoadList(string file)
{
var count = downloadRequestList.Count;
for (var i = 0; i < count; ++i)
{
if (downloadRequestList[i].fileName == file)
{
return i;
}
}
return -1;
}
/// <summary>
/// 网络是否可用
/// </summary>
public bool IsNetworkReachable
{
get
{
return ((allowDowloadFromWWAN && curNetworkStatus == UnityEngine.NetworkReachability.ReachableViaCarrierDataNetwork)
|| curNetworkStatus == UnityEngine.NetworkReachability.ReachableViaLocalAreaNetwork);
}
}
/// <summary>
/// 更新网络状态
/// </summary>
void UpdateCurNetworkStatus()
{
NetworkReachability state = Application.internetReachability;
if (curNetworkStatus != state)
{
curNetworkStatus = state;
if (BaseLogger.isDebug) Debug.Log(string.Format("curNetworkStatus changed:{0}", curNetworkStatus));
if (!IsNetworkReachable)
{
ClearDownloadRequestList();
}
}
}
/// <summary>
/// 清理下载列表
/// </summary>
void ClearDownloadRequestList()
{
var count = downloadRequestList.Count;
for (var i = curDownloadingCount; i < count; i++)
{
var downloadRequest = downloadRequestList[i];
downloadRequest.FinishCallback();
downloadRequestPool.Release(downloadRequest);
}
downloadRequestList.RemoveRange(curDownloadingCount, count - curDownloadingCount);
if (BaseLogger.isDebug) BaseLogger.Log("Remove all waiting download file");
}
}
}