diff --git a/Assets/YooAsset/Runtime/PatchSystem/Download.meta b/Assets/YooAsset/Runtime/DownloadSystem.meta
similarity index 100%
rename from Assets/YooAsset/Runtime/PatchSystem/Download.meta
rename to Assets/YooAsset/Runtime/DownloadSystem.meta
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Download/DownloadSystem.cs b/Assets/YooAsset/Runtime/DownloadSystem/DownloadSystem.cs
similarity index 100%
rename from Assets/YooAsset/Runtime/PatchSystem/Download/DownloadSystem.cs
rename to Assets/YooAsset/Runtime/DownloadSystem/DownloadSystem.cs
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Download/DownloadSystem.cs.meta b/Assets/YooAsset/Runtime/DownloadSystem/DownloadSystem.cs.meta
similarity index 100%
rename from Assets/YooAsset/Runtime/PatchSystem/Download/DownloadSystem.cs.meta
rename to Assets/YooAsset/Runtime/DownloadSystem/DownloadSystem.cs.meta
diff --git a/Assets/YooAsset/Runtime/DownloadSystem/DownloaderBase.cs b/Assets/YooAsset/Runtime/DownloadSystem/DownloaderBase.cs
new file mode 100644
index 0000000..359eec3
--- /dev/null
+++ b/Assets/YooAsset/Runtime/DownloadSystem/DownloaderBase.cs
@@ -0,0 +1,122 @@
+
+namespace YooAsset
+{
+ internal abstract class DownloaderBase
+ {
+ protected enum ESteps
+ {
+ None,
+ CreateDownload,
+ CheckDownload,
+ TryAgain,
+ Succeed,
+ Failed,
+ }
+
+ protected readonly BundleInfo _bundleInfo;
+
+ protected ESteps _steps = ESteps.None;
+
+ protected int _timeout;
+ protected int _failedTryAgain;
+ protected int _requestCount;
+ protected string _requestURL;
+
+ protected string _lastError = string.Empty;
+ protected float _downloadProgress = 0f;
+ protected ulong _downloadedBytes = 0;
+
+
+ ///
+ /// 下载进度(0-100f)
+ ///
+ public float DownloadProgress
+ {
+ get { return _downloadProgress; }
+ }
+
+ ///
+ /// 已经下载的总字节数
+ ///
+ public ulong DownloadedBytes
+ {
+ get { return _downloadedBytes; }
+ }
+
+
+ internal DownloaderBase(BundleInfo bundleInfo)
+ {
+ _bundleInfo = bundleInfo;
+ }
+ internal void SendRequest(int failedTryAgain, int timeout)
+ {
+ if (string.IsNullOrEmpty(_bundleInfo.LocalPath))
+ throw new System.ArgumentNullException();
+
+ if (_steps == ESteps.None)
+ {
+ _failedTryAgain = failedTryAgain;
+ _timeout = timeout;
+ _steps = ESteps.CreateDownload;
+ }
+ }
+ internal void SetDone()
+ {
+ _steps = ESteps.Succeed;
+ }
+ internal abstract void Update();
+
+ ///
+ /// 获取网络请求地址
+ ///
+ protected string GetRequestURL()
+ {
+ // 轮流返回请求地址
+ _requestCount++;
+ if (_requestCount % 2 == 0)
+ return _bundleInfo.RemoteFallbackURL;
+ else
+ return _bundleInfo.RemoteMainURL;
+ }
+
+ ///
+ /// 获取资源包信息
+ ///
+ public BundleInfo GetBundleInfo()
+ {
+ return _bundleInfo;
+ }
+
+ ///
+ /// 检测下载器是否已经完成(无论成功或失败)
+ ///
+ public bool IsDone()
+ {
+ return _steps == ESteps.Succeed || _steps == ESteps.Failed;
+ }
+
+ ///
+ /// 下载过程是否发生错误
+ ///
+ public bool HasError()
+ {
+ return _steps == ESteps.Failed;
+ }
+
+ ///
+ /// 报告错误信息
+ ///
+ public void ReportError()
+ {
+ YooLogger.Error($"Failed to download : {_requestURL} Error : {_lastError}");
+ }
+
+ ///
+ /// 获取最近一条错误日志
+ ///
+ public string GetLastError()
+ {
+ return _lastError;
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/YooAsset/Runtime/DownloadSystem/DownloaderBase.cs.meta b/Assets/YooAsset/Runtime/DownloadSystem/DownloaderBase.cs.meta
new file mode 100644
index 0000000..0a53087
--- /dev/null
+++ b/Assets/YooAsset/Runtime/DownloadSystem/DownloaderBase.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: dda4d1eafa2c9f34fade509f8dae9c04
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Download/FileDownloader.cs b/Assets/YooAsset/Runtime/DownloadSystem/FileDownloader.cs
similarity index 53%
rename from Assets/YooAsset/Runtime/PatchSystem/Download/FileDownloader.cs
rename to Assets/YooAsset/Runtime/DownloadSystem/FileDownloader.cs
index 3c29c5b..b23913a 100644
--- a/Assets/YooAsset/Runtime/PatchSystem/Download/FileDownloader.cs
+++ b/Assets/YooAsset/Runtime/DownloadSystem/FileDownloader.cs
@@ -7,82 +7,39 @@ using UnityEngine.Networking;
namespace YooAsset
{
- internal class FileDownloader
+ internal sealed class FileDownloader : DownloaderBase
{
- private enum ESteps
- {
- None,
- CreateDownload,
- CheckDownload,
- TryAgain,
- Succeed,
- Failed,
- }
-
- private readonly BundleInfo _bundleInfo;
private UnityWebRequest _webRequest;
private UnityWebRequestAsyncOperation _operationHandle;
- private ESteps _steps = ESteps.None;
- private string _lastError = string.Empty;
-
- private int _timeout;
- private int _failedTryAgain;
- private int _requestCount;
- private string _requestURL;
-
// 重置变量
private bool _isAbort = false;
private ulong _latestDownloadBytes;
private float _latestDownloadRealtime;
private float _tryAgainTimer;
- ///
- /// 下载进度(0-100f)
- ///
- public float DownloadProgress { private set; get; }
- ///
- /// 已经下载的总字节数
- ///
- public ulong DownloadedBytes { private set; get; }
-
-
- internal FileDownloader(BundleInfo bundleInfo)
+ internal FileDownloader(BundleInfo bundleInfo) : base(bundleInfo)
{
- _bundleInfo = bundleInfo;
}
- internal void SendRequest(int failedTryAgain, int timeout)
- {
- if (string.IsNullOrEmpty(_bundleInfo.LocalPath))
- throw new ArgumentNullException();
-
- if (_steps == ESteps.None)
- {
- _failedTryAgain = failedTryAgain;
- _timeout = timeout;
- _steps = ESteps.CreateDownload;
- }
- }
- internal void Update()
+ internal override void Update()
{
if (_steps == ESteps.None)
return;
- if (_steps == ESteps.Failed || _steps == ESteps.Succeed)
+ if (IsDone())
return;
// 创建下载器
if (_steps == ESteps.CreateDownload)
{
// 重置变量
- DownloadProgress = 0f;
- DownloadedBytes = 0;
+ _downloadProgress = 0f;
+ _downloadedBytes = 0;
_isAbort = false;
_latestDownloadBytes = 0;
_latestDownloadRealtime = Time.realtimeSinceStartup;
_tryAgainTimer = 0f;
- _requestCount++;
_requestURL = GetRequestURL();
_webRequest = new UnityWebRequest(_requestURL, UnityWebRequest.kHttpVerbGET);
DownloadHandlerFile handler = new DownloadHandlerFile(_bundleInfo.LocalPath);
@@ -96,8 +53,8 @@ namespace YooAsset
// 检测下载结果
if (_steps == ESteps.CheckDownload)
{
- DownloadProgress = _webRequest.downloadProgress * 100f;
- DownloadedBytes = _webRequest.downloadedBytes;
+ _downloadProgress = _webRequest.downloadProgress * 100f;
+ _downloadedBytes = _webRequest.downloadedBytes;
if (_operationHandle.isDone == false)
{
CheckTimeout();
@@ -105,47 +62,50 @@ namespace YooAsset
}
// 检查网络错误
- bool isError = false;
+ bool hasError = false;
#if UNITY_2020_3_OR_NEWER
if (_webRequest.result != UnityWebRequest.Result.Success)
{
- isError = true;
+ hasError = true;
_lastError = _webRequest.error;
}
#else
if (_webRequest.isNetworkError || _webRequest.isHttpError)
{
- isError = true;
+ hasError = true;
_lastError = _webRequest.error;
}
#endif
// 检查文件完整性
- if (isError == false)
+ if (hasError == false)
{
// 注意:如果文件验证失败需要删除文件
if (DownloadSystem.CheckContentIntegrity(_bundleInfo) == false)
{
- isError = true;
- _lastError = $"Verification failed";
- if (File.Exists(_bundleInfo.LocalPath))
- File.Delete(_bundleInfo.LocalPath);
+ hasError = true;
+ _lastError = $"Verification failed";
}
}
- if (isError)
+ if (hasError == false)
+ {
+ _steps = ESteps.Succeed;
+ DownloadSystem.CacheVerifyFile(_bundleInfo.Hash, _bundleInfo.BundleName);
+ }
+ else
{
ReportError();
+
+ if (File.Exists(_bundleInfo.LocalPath))
+ File.Delete(_bundleInfo.LocalPath);
+
+ // 失败后重新尝试
if (_failedTryAgain > 0)
_steps = ESteps.TryAgain;
else
_steps = ESteps.Failed;
}
- else
- {
- _steps = ESteps.Succeed;
- DownloadSystem.CacheVerifyFile(_bundleInfo.Hash, _bundleInfo.BundleName);
- }
// 释放下载器
DisposeWebRequest();
@@ -155,7 +115,7 @@ namespace YooAsset
if (_steps == ESteps.TryAgain)
{
_tryAgainTimer += Time.unscaledDeltaTime;
- if (_tryAgainTimer > 0.5f)
+ if (_tryAgainTimer > 1f)
{
_failedTryAgain--;
_steps = ESteps.CreateDownload;
@@ -163,19 +123,6 @@ namespace YooAsset
}
}
}
- internal void SetDone()
- {
- _steps = ESteps.Succeed;
- }
-
- private string GetRequestURL()
- {
- // 轮流返回请求地址
- if (_requestCount % 2 == 0)
- return _bundleInfo.RemoteFallbackURL;
- else
- return _bundleInfo.RemoteMainURL;
- }
private void CheckTimeout()
{
// 注意:在连续时间段内无新增下载数据及判定为超时
@@ -205,46 +152,5 @@ namespace YooAsset
_operationHandle = null;
}
}
-
- ///
- /// 获取资源包信息
- ///
- public BundleInfo GetBundleInfo()
- {
- return _bundleInfo;
- }
-
- ///
- /// 检测下载器是否已经完成(无论成功或失败)
- ///
- public bool IsDone()
- {
- return _steps == ESteps.Succeed || _steps == ESteps.Failed;
- }
-
- ///
- /// 下载过程是否发生错误
- ///
- ///
- public bool HasError()
- {
- return _steps == ESteps.Failed;
- }
-
- ///
- /// 报告错误信息
- ///
- public void ReportError()
- {
- YooLogger.Error($"Failed to download : {_requestURL} Error : {_lastError}");
- }
-
- ///
- /// 获取最近一条错误日志
- ///
- public string GetLastError()
- {
- return _lastError;
- }
}
}
\ No newline at end of file
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Download/FileDownloader.cs.meta b/Assets/YooAsset/Runtime/DownloadSystem/FileDownloader.cs.meta
similarity index 100%
rename from Assets/YooAsset/Runtime/PatchSystem/Download/FileDownloader.cs.meta
rename to Assets/YooAsset/Runtime/DownloadSystem/FileDownloader.cs.meta
diff --git a/Assets/YooAsset/Runtime/DownloadSystem/HttpDownloader.cs b/Assets/YooAsset/Runtime/DownloadSystem/HttpDownloader.cs
new file mode 100644
index 0000000..4e71828
--- /dev/null
+++ b/Assets/YooAsset/Runtime/DownloadSystem/HttpDownloader.cs
@@ -0,0 +1,243 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.IO;
+using System.Net;
+using System.Net.Security;
+using System.Threading;
+
+namespace YooAsset
+{
+ internal sealed class HttpDownloader : DownloaderBase
+ {
+ ///
+ /// 多线程下载器
+ ///
+ private class ThreadDownloader
+ {
+ private const int BufferSize = 1042 * 4;
+
+ private Thread _thread;
+ private string _url;
+ private string _savePath;
+ private string _fileHash;
+ private string _fileCRC;
+ private long _fileSize;
+ private int _timeout;
+
+ ///
+ /// 下载是否结束
+ ///
+ public bool IsDone = false;
+
+ ///
+ /// 下载结果(成功或失败)
+ ///
+ public bool Result = false;
+
+ ///
+ /// 错误日志
+ ///
+ public string Error = string.Empty;
+
+ ///
+ /// 下载进度
+ ///
+ public float DownloadProgress = 0f;
+
+ ///
+ /// 已经下载的总字节数
+ ///
+ public ulong DownloadedBytes = 0;
+
+
+ ///
+ /// 开始下载
+ ///
+ public void Run(string url, string savePath, string fileHash, string fileCRC, long fileSize, int timeout)
+ {
+ _url = url;
+ _savePath = savePath;
+ _fileHash = fileHash;
+ _fileCRC = fileCRC;
+ _fileSize = fileSize;
+ _timeout = timeout;
+
+ _thread = new Thread(ThreadRun);
+ _thread.IsBackground = true;
+ _thread.Start();
+ }
+
+ ///
+ /// 销毁下载器
+ ///
+ public void Dispose()
+ {
+ if (_thread != null)
+ {
+ _thread.Abort();
+ _thread = null;
+ }
+ }
+
+
+ private void ThreadRun()
+ {
+ long fileTotalSize = _fileSize;
+
+ FileStream fileStream = null;
+ Stream webStream = null;
+ HttpWebResponse fileResponse = null;
+
+ try
+ {
+ // 创建文件流
+ fileStream = new FileStream(_savePath, FileMode.OpenOrCreate, FileAccess.Write);
+ long fileLength = fileStream.Length;
+
+ // 创建HTTP下载请求
+ HttpWebRequest fileRequest = WebRequest.Create(_url) as HttpWebRequest;
+ fileRequest.Timeout = _timeout;
+ fileRequest.ReadWriteTimeout = _timeout;
+ fileRequest.ProtocolVersion = HttpVersion.Version10;
+ if (fileLength > 0)
+ {
+ // 注意:设置远端请求文件的起始位置
+ fileRequest.AddRange(fileLength);
+ // 注意:设置本地文件流的起始位置
+ fileStream.Seek(fileLength, SeekOrigin.Begin);
+ }
+
+ // 读取下载数据并保存到文件
+ fileResponse = fileRequest.GetResponse() as HttpWebResponse;
+ webStream = fileResponse.GetResponseStream();
+ byte[] buffer = new byte[BufferSize];
+ while (true)
+ {
+ int length = webStream.Read(buffer, 0, buffer.Length);
+ if (length <= 0)
+ break;
+
+ fileStream.Write(buffer, 0, length);
+
+ // 计算下载进度
+ // 注意:原子操作保证数据安全
+ fileLength += length;
+ float progress = fileLength / fileTotalSize;
+ DownloadProgress = progress;
+ DownloadedBytes = (ulong)fileLength;
+ }
+
+ // 验证下载文件完整性
+ bool verfiyResult = DownloadSystem.CheckContentIntegrity(_savePath, _fileSize, _fileCRC);
+ if (verfiyResult)
+ {
+ Result = true;
+ }
+ else
+ {
+ Result = false;
+ Error = $"Verify file content failed : {_fileHash}";
+ }
+ }
+ catch (Exception e)
+ {
+ Result = false;
+ Error = e.Message;
+ }
+ finally
+ {
+ if (webStream != null)
+ {
+ webStream.Close();
+ webStream.Dispose();
+ }
+
+ if (fileResponse != null)
+ {
+ fileResponse.Close();
+ }
+
+ if (fileStream != null)
+ {
+ fileStream.Close();
+ fileStream.Dispose();
+ }
+
+ IsDone = true;
+ }
+ }
+ }
+
+
+ private ThreadDownloader _threadDownloader;
+ private float _tryAgainTimer;
+
+ internal HttpDownloader(BundleInfo bundleInfo) : base(bundleInfo)
+ {
+ }
+ internal override void Update()
+ {
+ if (_steps == ESteps.None)
+ return;
+ if (IsDone())
+ return;
+
+ if (_steps == ESteps.CreateDownload)
+ {
+ // 重置变量
+ _downloadProgress = 0f;
+ _downloadedBytes = 0;
+ _tryAgainTimer = 0f;
+
+ _requestURL = GetRequestURL();
+ _threadDownloader = new ThreadDownloader();
+ _threadDownloader.Run(_requestURL, _bundleInfo.LocalPath, _bundleInfo.Hash, _bundleInfo.CRC, _bundleInfo.SizeBytes, _timeout);
+ _steps = ESteps.CheckDownload;
+ }
+
+ if (_steps == ESteps.CheckDownload)
+ {
+ _downloadProgress = _threadDownloader.DownloadProgress * 100f;
+ _downloadedBytes = _threadDownloader.DownloadedBytes;
+ if (_threadDownloader.IsDone == false)
+ return;
+
+ if (_threadDownloader.Result)
+ {
+ DownloadSystem.CacheVerifyFile(_bundleInfo.Hash, _bundleInfo.BundleName);
+ _steps = ESteps.Succeed;
+ }
+ else
+ {
+ _lastError = _threadDownloader.Error;
+ ReportError();
+
+ if (File.Exists(_bundleInfo.LocalPath))
+ File.Delete(_bundleInfo.LocalPath);
+
+ // 失败后重新尝试
+ if (_failedTryAgain > 0)
+ _steps = ESteps.TryAgain;
+ else
+ _steps = ESteps.Failed;
+ }
+
+ // 释放下载器
+ _threadDownloader.Dispose();
+ }
+
+ // 重新尝试下载
+ if (_steps == ESteps.TryAgain)
+ {
+ _tryAgainTimer += UnityEngine.Time.unscaledDeltaTime;
+ if (_tryAgainTimer > 1f)
+ {
+ _failedTryAgain--;
+ _steps = ESteps.CreateDownload;
+ YooLogger.Warning($"Try again download : {_requestURL}");
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Download/HttpDownloader.cs.meta b/Assets/YooAsset/Runtime/DownloadSystem/HttpDownloader.cs.meta
similarity index 100%
rename from Assets/YooAsset/Runtime/PatchSystem/Download/HttpDownloader.cs.meta
rename to Assets/YooAsset/Runtime/DownloadSystem/HttpDownloader.cs.meta
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Download/ThreadSyncContext.cs b/Assets/YooAsset/Runtime/DownloadSystem/ThreadSyncContext.cs
similarity index 100%
rename from Assets/YooAsset/Runtime/PatchSystem/Download/ThreadSyncContext.cs
rename to Assets/YooAsset/Runtime/DownloadSystem/ThreadSyncContext.cs
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Download/ThreadSyncContext.cs.meta b/Assets/YooAsset/Runtime/DownloadSystem/ThreadSyncContext.cs.meta
similarity index 100%
rename from Assets/YooAsset/Runtime/PatchSystem/Download/ThreadSyncContext.cs.meta
rename to Assets/YooAsset/Runtime/DownloadSystem/ThreadSyncContext.cs.meta
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Download/UnityWebDataRequester.cs b/Assets/YooAsset/Runtime/DownloadSystem/UnityWebDataRequester.cs
similarity index 100%
rename from Assets/YooAsset/Runtime/PatchSystem/Download/UnityWebDataRequester.cs
rename to Assets/YooAsset/Runtime/DownloadSystem/UnityWebDataRequester.cs
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Download/UnityWebDataRequester.cs.meta b/Assets/YooAsset/Runtime/DownloadSystem/UnityWebDataRequester.cs.meta
similarity index 100%
rename from Assets/YooAsset/Runtime/PatchSystem/Download/UnityWebDataRequester.cs.meta
rename to Assets/YooAsset/Runtime/DownloadSystem/UnityWebDataRequester.cs.meta
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Download/UnityWebFileRequester.cs b/Assets/YooAsset/Runtime/DownloadSystem/UnityWebFileRequester.cs
similarity index 100%
rename from Assets/YooAsset/Runtime/PatchSystem/Download/UnityWebFileRequester.cs
rename to Assets/YooAsset/Runtime/DownloadSystem/UnityWebFileRequester.cs
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Download/UnityWebFileRequester.cs.meta b/Assets/YooAsset/Runtime/DownloadSystem/UnityWebFileRequester.cs.meta
similarity index 100%
rename from Assets/YooAsset/Runtime/PatchSystem/Download/UnityWebFileRequester.cs.meta
rename to Assets/YooAsset/Runtime/DownloadSystem/UnityWebFileRequester.cs.meta
diff --git a/Assets/YooAsset/Runtime/PatchSystem/Download/HttpDownloader.cs b/Assets/YooAsset/Runtime/PatchSystem/Download/HttpDownloader.cs
deleted file mode 100644
index a482dd2..0000000
--- a/Assets/YooAsset/Runtime/PatchSystem/Download/HttpDownloader.cs
+++ /dev/null
@@ -1,266 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using System.Net;
-using System.Net.Security;
-using System.Threading;
-
-namespace YooAsset
-{
- internal class HttpDownloader
- {
- private enum ESteps
- {
- None,
- CreateDownload,
- CheckDownload,
- Succeed,
- Failed,
- }
-
- private readonly BundleInfo _bundleInfo;
- private ESteps _steps = ESteps.None;
-
- // 线程
- private bool _threadOver = false;
- private bool _threadResult = false;
- private string _threadError = string.Empty;
- private Thread _thread;
-
- // 保留参数
- private int _timeout;
- private int _failedTryAgain;
- private int _requestCount;
-
- // 下载结果
- private string _downloadError = string.Empty;
- private float _downloadProgress = 0f;
- private long _downloadBytes = 0;
-
- ///
- /// 下载进度(0-100f)
- ///
- public float DownloadProgress
- {
- get
- {
- return _downloadProgress;
- }
- }
-
- ///
- /// 已经下载的总字节数
- ///
- public long DownloadedBytes
- {
- get
- {
- return _downloadBytes;
- }
- }
-
-
- internal HttpDownloader(BundleInfo bundleInfo)
- {
- _bundleInfo = bundleInfo;
- }
- internal void SendRequest(int failedTryAgain, int timeout)
- {
- _failedTryAgain = failedTryAgain;
- _timeout = timeout;
- }
- internal void Update()
- {
- if (_steps == ESteps.None)
- return;
- if (_steps == ESteps.Succeed || _steps == ESteps.Failed)
- return;
-
- if(_steps == ESteps.CreateDownload)
- {
- _downloadError = string.Empty;
- _downloadProgress = 0f;
- _downloadBytes = 0;
-
- _threadOver = false;
- _threadResult = false;
- _threadError = string.Empty;
- _thread = new Thread(ThreadRun);
- _thread.IsBackground = true;
- _thread.Start();
- _steps = ESteps.CheckDownload;
- }
-
- if(_steps == ESteps.CheckDownload)
- {
- if (_threadOver == false)
- return;
-
- if(_thread != null)
- {
- _thread.Abort();
- _thread = null;
- }
-
- _downloadError = _threadError;
- if (_threadResult)
- {
- DownloadSystem.CacheVerifyFile(_bundleInfo.Hash, _bundleInfo.BundleName);
- _steps = ESteps.Succeed;
- }
- else
- {
- // 失败后重新尝试
- if(_failedTryAgain > 0)
- {
- _failedTryAgain--;
- _steps = ESteps.CreateDownload;
- }
- else
- {
- _steps = ESteps.Failed;
- }
- }
- }
- }
- internal void SetDone()
- {
- _steps = ESteps.Succeed;
- }
-
- ///
- /// 获取资源包信息
- ///
- public BundleInfo GetBundleInfo()
- {
- return _bundleInfo;
- }
-
- ///
- /// 检测下载器是否已经完成(无论成功或失败)
- ///
- public bool IsDone()
- {
- return _steps == ESteps.Succeed || _steps == ESteps.Failed;
- }
-
- ///
- /// 下载过程是否发生错误
- ///
- public bool HasError()
- {
- return _steps == ESteps.Failed;
- }
-
- ///
- /// 报告错误信息
- ///
- public void ReportError()
- {
- YooLogger.Error(_downloadError);
- }
-
-
- #region 多线程下载
- public const int BufferSize = 1042 * 4;
- private void ThreadRun()
- {
- string url = GetRequestURL();
- string savePath = _bundleInfo.LocalPath;
- long fileTotalSize = _bundleInfo.SizeBytes;
-
- FileStream fileStream = null;
- Stream webStream = null;
- HttpWebResponse fileResponse = null;
-
- try
- {
- // 创建文件流
- fileStream = new FileStream(savePath, FileMode.OpenOrCreate, FileAccess.Write);
- long fileLength = fileStream.Length;
-
- // 创建HTTP下载请求
- HttpWebRequest fileRequest = WebRequest.Create(url) as HttpWebRequest;
- fileRequest.Timeout = _timeout;
- fileRequest.ReadWriteTimeout = _timeout;
- fileRequest.ProtocolVersion = HttpVersion.Version10;
- if (fileLength > 0)
- {
- // 注意:设置远端请求文件的起始位置
- fileRequest.AddRange(fileLength);
- // 注意:设置本地文件流的起始位置
- fileStream.Seek(fileLength, SeekOrigin.Begin);
- }
-
- // 读取下载数据并保存到文件
- fileResponse = fileRequest.GetResponse() as HttpWebResponse;
- webStream = fileResponse.GetResponseStream();
- byte[] buffer = new byte[BufferSize];
- while (true)
- {
- int length = webStream.Read(buffer, 0, buffer.Length);
- if (length <= 0)
- break;
-
- fileStream.Write(buffer, 0, length);
-
- // 计算下载进度
- // 注意:原子操作保证数据安全
- fileLength += length;
- float progress = (fileLength / fileTotalSize) * 100f;
- _downloadProgress = progress;
- _downloadBytes = fileLength;
- }
-
- // 验证下载文件完整性
- bool verfiyResult = DownloadSystem.CheckContentIntegrity(savePath, _bundleInfo.SizeBytes, _bundleInfo.CRC);
- if(verfiyResult)
- {
- _threadResult = true;
- }
- else
- {
- _threadResult = false;
- _threadError = $"Verify file content failed : {_bundleInfo.Hash}";
- }
- }
- catch (Exception e)
- {
- _threadResult = false;
- _threadError = e.Message;
- }
- finally
- {
- if (webStream != null)
- {
- webStream.Close();
- webStream.Dispose();
- }
-
- if (fileResponse != null)
- {
- fileResponse.Close();
- }
-
- if (fileStream != null)
- {
- fileStream.Close();
- fileStream.Dispose();
- }
-
- _threadOver = true;
- }
- }
- private string GetRequestURL()
- {
- // 轮流返回请求地址
- _requestCount++;
- if (_requestCount % 2 == 0)
- return _bundleInfo.RemoteFallbackURL;
- else
- return _bundleInfo.RemoteMainURL;
- }
- #endregion
- }
-}
\ No newline at end of file