update download system

优化资源文件下载流程。
pull/62/head
hevinci 2022-12-13 23:30:16 +08:00
parent 15a605b677
commit 7b9fda2298
5 changed files with 155 additions and 98 deletions

View File

@ -73,9 +73,9 @@ namespace YooAsset
}
/// <summary>
/// 验证并缓存补丁包文件
/// 验证并缓存本地文件
/// </summary>
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;
}
/// <summary>
/// 验证并缓存下载文件
/// </summary>
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;
}
/// <summary>
/// 验证文件完整性
/// </summary>
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
{

View File

@ -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);

View File

@ -9,7 +9,12 @@ namespace YooAsset
/// <summary>
/// 文件不存在
/// </summary>
FileNotExisted = -4,
FileNotExisted = -5,
/// <summary>
/// 文件移动失败(重命名失败)
/// </summary>
FileMoveFailed = -4,
/// <summary>
/// 文件内容不足(小于正常大小)

View File

@ -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();

View File

@ -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}");
}
}