400 lines
12 KiB
C#
400 lines
12 KiB
C#
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");
|
||
}
|
||
}
|
||
}
|