diff --git a/Assets/YooAsset/Runtime/CacheSystem/CacheSystem.cs b/Assets/YooAsset/Runtime/CacheSystem/CacheSystem.cs
index 3ee5b92..726ab84 100644
--- a/Assets/YooAsset/Runtime/CacheSystem/CacheSystem.cs
+++ b/Assets/YooAsset/Runtime/CacheSystem/CacheSystem.cs
@@ -73,9 +73,9 @@ namespace YooAsset
}
///
- /// 验证并缓存补丁包文件
+ /// 验证并缓存本地文件
///
- public static EVerifyResult VerifyAndCacheBundle(PatchBundle patchBundle, EVerifyLevel verifyLevel)
+ public static EVerifyResult VerifyAndCacheLocalBundleFile(PatchBundle patchBundle, EVerifyLevel verifyLevel)
{
var verifyResult = VerifyContentInternal(patchBundle.CachedFilePath, patchBundle.FileSize, patchBundle.FileCRC, verifyLevel);
if (verifyResult == EVerifyResult.Succeed)
@@ -83,10 +83,41 @@ namespace YooAsset
return verifyResult;
}
+ ///
+ /// 验证并缓存下载文件
+ ///
+ public static EVerifyResult VerifyAndCacheDownloadBundleFile(PatchBundle patchBundle, EVerifyLevel verifyLevel)
+ {
+ string tempFilePath = patchBundle.CachedFilePath + ".temp";
+ var verifyResult = VerifyContentInternal(tempFilePath, patchBundle.FileSize, patchBundle.FileCRC, verifyLevel);
+ if (verifyResult == EVerifyResult.Succeed)
+ {
+ try
+ {
+ string destFilePath = patchBundle.CachedFilePath;
+ if (File.Exists(destFilePath))
+ File.Delete(destFilePath);
+
+ FileInfo fileInfo = new FileInfo(tempFilePath);
+ fileInfo.MoveTo(destFilePath);
+ }
+ catch (Exception)
+ {
+ verifyResult = EVerifyResult.FileMoveFailed;
+ }
+
+ if (verifyResult == EVerifyResult.Succeed)
+ {
+ CacheBundle(patchBundle);
+ }
+ }
+ return verifyResult;
+ }
+
///
/// 验证文件完整性
///
- public static EVerifyResult VerifyContentInternal(string filePath, long fileSize, string fileCRC, EVerifyLevel verifyLevel)
+ private static EVerifyResult VerifyContentInternal(string filePath, long fileSize, string fileCRC, EVerifyLevel verifyLevel)
{
try
{
diff --git a/Assets/YooAsset/Runtime/CacheSystem/CacheVerifier.cs b/Assets/YooAsset/Runtime/CacheSystem/CacheVerifier.cs
index 67ceee9..fd97b20 100644
--- a/Assets/YooAsset/Runtime/CacheSystem/CacheVerifier.cs
+++ b/Assets/YooAsset/Runtime/CacheSystem/CacheVerifier.cs
@@ -161,7 +161,7 @@ namespace YooAsset
private void VerifyFileWithoutThread(VerifyInfo verifyIno)
{
- var verifyResult = CacheSystem.VerifyAndCacheBundle(verifyIno.VerifyBundle, CacheSystem.InitVerifyLevel);
+ var verifyResult = CacheSystem.VerifyAndCacheLocalBundleFile(verifyIno.VerifyBundle, CacheSystem.InitVerifyLevel);
if (verifyResult == EVerifyResult.Succeed)
{
VerifySuccessList.Add(verifyIno);
diff --git a/Assets/YooAsset/Runtime/CacheSystem/EVerifyResult.cs b/Assets/YooAsset/Runtime/CacheSystem/EVerifyResult.cs
index 6d4b48f..8179f08 100644
--- a/Assets/YooAsset/Runtime/CacheSystem/EVerifyResult.cs
+++ b/Assets/YooAsset/Runtime/CacheSystem/EVerifyResult.cs
@@ -9,7 +9,12 @@ namespace YooAsset
///
/// 文件不存在
///
- FileNotExisted = -4,
+ FileNotExisted = -5,
+
+ ///
+ /// 文件移动失败(重命名失败)
+ ///
+ FileMoveFailed = -4,
///
/// 文件内容不足(小于正常大小)
diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Downloader/DownloaderBase.cs b/Assets/YooAsset/Runtime/DownloadSystem/Downloader/DownloaderBase.cs
index bcd04dc..f83031e 100644
--- a/Assets/YooAsset/Runtime/DownloadSystem/Downloader/DownloaderBase.cs
+++ b/Assets/YooAsset/Runtime/DownloadSystem/Downloader/DownloaderBase.cs
@@ -6,9 +6,12 @@ namespace YooAsset
protected enum ESteps
{
None,
- CheckLocalFile,
- CreateDownload,
+ CheckTempFile,
+ PrepareDownload,
+ CreateResumeDownloader,
+ CreateGeneralDownloader,
CheckDownload,
+ VerifyDownload,
TryAgain,
Succeed,
Failed,
@@ -56,7 +59,7 @@ namespace YooAsset
{
_failedTryAgain = failedTryAgain;
_timeout = timeout;
- _steps = ESteps.CheckLocalFile;
+ _steps = ESteps.CheckTempFile;
}
}
public abstract void Update();
diff --git a/Assets/YooAsset/Runtime/DownloadSystem/Downloader/FileDownloader.cs b/Assets/YooAsset/Runtime/DownloadSystem/Downloader/FileDownloader.cs
index a80b403..fc5b3d4 100644
--- a/Assets/YooAsset/Runtime/DownloadSystem/Downloader/FileDownloader.cs
+++ b/Assets/YooAsset/Runtime/DownloadSystem/Downloader/FileDownloader.cs
@@ -10,6 +10,7 @@ namespace YooAsset
internal sealed class FileDownloader : DownloaderBase
{
private readonly bool _breakResume;
+ private readonly string _tempFilePath;
private UnityWebRequest _webRequest = null;
private DownloadHandlerFileRange _downloadHandle = null;
@@ -24,6 +25,7 @@ namespace YooAsset
public FileDownloader(BundleInfo bundleInfo, bool breakResume) : base(bundleInfo)
{
_breakResume = breakResume;
+ _tempFilePath = bundleInfo.Bundle.CachedFilePath + ".temp";
}
public override void Update()
{
@@ -33,9 +35,9 @@ namespace YooAsset
return;
// 检测本地文件
- if (_steps == ESteps.CheckLocalFile)
+ if (_steps == ESteps.CheckTempFile)
{
- var verifyResult = CacheSystem.VerifyAndCacheBundle(_bundleInfo.Bundle, EVerifyLevel.High);
+ var verifyResult = CacheSystem.VerifyAndCacheDownloadBundleFile(_bundleInfo.Bundle, EVerifyLevel.High);
if (verifyResult == EVerifyResult.Succeed)
{
_steps = ESteps.Succeed;
@@ -44,19 +46,16 @@ namespace YooAsset
{
if (verifyResult == EVerifyResult.FileOverflow)
{
- string cacheFilePath = _bundleInfo.Bundle.CachedFilePath;
- if (File.Exists(cacheFilePath))
- File.Delete(cacheFilePath);
+ if (File.Exists(_tempFilePath))
+ File.Delete(_tempFilePath);
}
- _steps = ESteps.CreateDownload;
+ _steps = ESteps.PrepareDownload;
}
}
// 创建下载器
- if (_steps == ESteps.CreateDownload)
+ if (_steps == ESteps.PrepareDownload)
{
- string fileSavePath = _bundleInfo.Bundle.CachedFilePath;
-
// 重置变量
_downloadProgress = 0f;
_downloadedBytes = 0;
@@ -66,53 +65,73 @@ namespace YooAsset
_latestDownloadRealtime = Time.realtimeSinceStartup;
_tryAgainTimer = 0f;
- // 是否开启断点续传下载
- if (_breakResume)
- {
- long fileLength = -1;
- if (File.Exists(fileSavePath))
- {
- FileInfo fileInfo = new FileInfo(fileSavePath);
- fileLength = fileInfo.Length;
- _fileOriginLength = (ulong)fileLength;
- _downloadedBytes = _fileOriginLength;
- }
+ // 获取请求地址
+ _requestURL = GetRequestURL();
- _requestURL = GetRequestURL();
- _webRequest = UnityWebRequest.Get(_requestURL);
+ if (_breakResume)
+ _steps = ESteps.CreateResumeDownloader;
+ else
+ _steps = ESteps.CreateGeneralDownloader;
+ }
+
+ // 创建普通的下载器
+ if (_steps == ESteps.CreateGeneralDownloader)
+ {
+ if (File.Exists(_tempFilePath))
+ {
+ File.Delete(_tempFilePath);
+ }
+
+ _webRequest = new UnityWebRequest(_requestURL, UnityWebRequest.kHttpVerbGET);
+ DownloadHandlerFile handler = new DownloadHandlerFile(_tempFilePath);
+ handler.removeFileOnAbort = true;
+ _webRequest.downloadHandler = handler;
+ _webRequest.disposeDownloadHandlerOnDispose = true;
+
+ if (DownloadSystem.CertificateHandlerInstance != null)
+ {
+ _webRequest.certificateHandler = DownloadSystem.CertificateHandlerInstance;
+ _webRequest.disposeCertificateHandlerOnDispose = false;
+ }
+
+ _webRequest.SendWebRequest();
+ _steps = ESteps.CheckDownload;
+ }
+
+ // 创建断点续传下载器
+ if (_steps == ESteps.CreateResumeDownloader)
+ {
+ long fileLength = -1;
+ if (File.Exists(_tempFilePath))
+ {
+ FileInfo fileInfo = new FileInfo(_tempFilePath);
+ fileLength = fileInfo.Length;
+ _fileOriginLength = (ulong)fileLength;
+ _downloadedBytes = _fileOriginLength;
+ }
#if UNITY_2019_4_OR_NEWER
- var handler = new DownloadHandlerFile(fileSavePath, true);
- handler.removeFileOnAbort = false;
+ _webRequest = new UnityWebRequest(_requestURL, UnityWebRequest.kHttpVerbGET);
+ var handler = new DownloadHandlerFile(_tempFilePath, true);
+ handler.removeFileOnAbort = false;
#else
- var handler = new DownloadHandlerFileRange(fileSavePath, _bundleInfo.Bundle.FileSize, _webRequest);
- _downloadHandle = handler;
+ _webRequest = new UnityWebRequest(_requestURL, UnityWebRequest.kHttpVerbGET);
+ var handler = new DownloadHandlerFileRange(_tempFilePath, _bundleInfo.Bundle.FileSize, _webRequest);
+ _downloadHandle = handler;
#endif
+ _webRequest.downloadHandler = handler;
+ _webRequest.disposeDownloadHandlerOnDispose = true;
+ if (fileLength > 0)
+ _webRequest.SetRequestHeader("Range", $"bytes={fileLength}-");
- if (DownloadSystem.CertificateHandlerInstance != null)
- {
- _webRequest.certificateHandler = DownloadSystem.CertificateHandlerInstance;
- _webRequest.disposeCertificateHandlerOnDispose = false;
- }
-
- _webRequest.downloadHandler = handler;
- _webRequest.disposeDownloadHandlerOnDispose = true;
- if (fileLength > 0)
- _webRequest.SetRequestHeader("Range", $"bytes={fileLength}-");
- _webRequest.SendWebRequest();
- _steps = ESteps.CheckDownload;
- }
- else
+ if (DownloadSystem.CertificateHandlerInstance != null)
{
- _requestURL = GetRequestURL();
- _webRequest = new UnityWebRequest(_requestURL, UnityWebRequest.kHttpVerbGET);
- DownloadHandlerFile handler = new DownloadHandlerFile(fileSavePath);
- handler.removeFileOnAbort = true;
- _webRequest.downloadHandler = handler;
- _webRequest.disposeDownloadHandlerOnDispose = true;
- _webRequest.SendWebRequest();
- _steps = ESteps.CheckDownload;
+ _webRequest.certificateHandler = DownloadSystem.CertificateHandlerInstance;
+ _webRequest.disposeCertificateHandlerOnDispose = false;
}
+
+ _webRequest.SendWebRequest();
+ _steps = ESteps.CheckDownload;
}
// 检测下载结果
@@ -145,78 +164,77 @@ namespace YooAsset
}
#endif
- // 检查文件完整性
- if (hasError == false)
- {
- var verifyResult = CacheSystem.VerifyAndCacheBundle(_bundleInfo.Bundle, EVerifyLevel.High);
- if (verifyResult != EVerifyResult.Succeed)
- {
- hasError = true;
- _lastError = $"Verify bundle content failed : {_bundleInfo.Bundle.FileName}";
- _lastCode = _webRequest.responseCode;
-
- // 验证失败后删除文件
- string cacheFilePath = _bundleInfo.Bundle.CachedFilePath;
- if (File.Exists(cacheFilePath))
- File.Delete(cacheFilePath);
- }
- }
-
- // 如果下载失败
+ // 如果网络异常
if (hasError)
{
- // 注意:非断点续传下载失败之后删除文件
- if (_breakResume == false)
- {
- string cacheFilePath = _bundleInfo.Bundle.CachedFilePath;
- if (File.Exists(cacheFilePath))
- File.Delete(cacheFilePath);
- }
- else
+ if (_breakResume)
{
// 注意:下载断点续传文件发生特殊错误码之后删除文件
if (DownloadSystem.ClearFileResponseCodes != null)
{
if (DownloadSystem.ClearFileResponseCodes.Contains(_webRequest.responseCode))
{
- string cacheFilePath = _bundleInfo.Bundle.CachedFilePath;
- if (File.Exists(cacheFilePath))
- File.Delete(cacheFilePath);
+ if (File.Exists(_tempFilePath))
+ File.Delete(_tempFilePath);
}
}
}
-
- // 失败后重新尝试
- if (_failedTryAgain > 0)
- {
- ReportWarning();
- _steps = ESteps.TryAgain;
- }
else
{
- ReportError();
- _steps = ESteps.Failed;
+ // 注意:非断点续传下载失败之后删除文件
+ if (File.Exists(_tempFilePath))
+ File.Delete(_tempFilePath);
}
+
+ _steps = ESteps.TryAgain;
}
else
{
- _lastError = string.Empty;
- _lastCode = 0;
- _steps = ESteps.Succeed;
+ _steps = ESteps.VerifyDownload;
}
// 释放下载器
DisposeWebRequest();
}
+ // 验证下载文件
+ if (_steps == ESteps.VerifyDownload)
+ {
+ var verifyResult = CacheSystem.VerifyAndCacheDownloadBundleFile(_bundleInfo.Bundle, EVerifyLevel.High);
+ if (verifyResult == EVerifyResult.Succeed)
+ {
+ _lastError = string.Empty;
+ _lastCode = 0;
+ _steps = ESteps.Succeed;
+ }
+ else
+ {
+ _lastError = $"Verify bundle content failed : {_bundleInfo.Bundle.FileName}";
+
+ // 验证失败后删除文件
+ if (File.Exists(_tempFilePath))
+ File.Delete(_tempFilePath);
+
+ _steps = ESteps.TryAgain;
+ }
+ }
+
// 重新尝试下载
if (_steps == ESteps.TryAgain)
{
+ if (_failedTryAgain <= 0)
+ {
+ ReportError();
+ _steps = ESteps.Failed;
+ return;
+ }
+
_tryAgainTimer += Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
_failedTryAgain--;
- _steps = ESteps.CreateDownload;
+ _steps = ESteps.PrepareDownload;
+ ReportWarning();
YooLogger.Warning($"Try again download : {_requestURL}");
}
}