Files
YooAssetScene/Assets/YooAsset/Runtime/FileSystem/DefaultCacheFileSystem/Operation/DCFSDownloadFileOperation.cs
何冠峰 ff02da5c54 refactor the runtime code
重构了运行时代码,支持全新的文件系统。
2024-07-04 20:36:26 +08:00

432 lines
14 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System.IO;
using UnityEngine;
using UnityEngine.Networking;
namespace YooAsset
{
internal sealed class DCFSDownloadNormalFileOperation : DefaultDownloadFileOperation
{
private readonly DefaultCacheFileSystem _fileSystem;
private VerifyTempFileOperation _verifyOperation;
private string _fileSavePath;
private ESteps _steps = ESteps.None;
internal DCFSDownloadNormalFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string mainURL, string fallbackURL, int failedTryAgain, int timeout)
: base(bundle, mainURL, fallbackURL, failedTryAgain, timeout)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
_fileSavePath = _fileSystem.GetTempFilePath(Bundle);
// 注意:检测文件是否存在
if (_fileSystem.Exists(Bundle))
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.CreateRequest;
}
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
// 创建下载器
if (_steps == ESteps.CreateRequest)
{
FileUtility.CreateFileDirectory(_fileSavePath);
// 获取请求地址
_requestURL = GetRequestURL();
// 重置变量
_isAbort = false;
_latestDownloadBytes = 0;
_latestDownloadRealtime = Time.realtimeSinceStartup;
DownloadProgress = 0f;
DownloadedBytes = 0;
// 重置计时器
if (_tryAgainTimer > 0f)
YooLogger.Warning($"Try again download : {_requestURL}");
_tryAgainTimer = 0f;
// 删除临时文件
if (File.Exists(_fileSavePath))
File.Delete(_fileSavePath);
// 创建下载器
CreateWebRequest();
_steps = ESteps.CheckRequest;
}
// 检测下载结果
if (_steps == ESteps.CheckRequest)
{
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = (long)_webRequest.downloadedBytes;
Progress = DownloadProgress;
if (_webRequest.isDone == false)
{
CheckRequestTimeout();
return;
}
// 检查网络错误
if (CheckRequestResult())
_steps = ESteps.VerifyTempFile;
else
_steps = ESteps.TryAgain;
// 注意:最终释放请求器
DisposeWebRequest();
}
// 验证下载文件
if (_steps == ESteps.VerifyTempFile)
{
var element = new TempFileElement(_fileSavePath, Bundle.FileCRC, Bundle.FileSize);
_verifyOperation = new VerifyTempFileOperation(element);
OperationSystem.StartOperation(_fileSystem.PackageName, _verifyOperation);
_steps = ESteps.CheckVerifyTempFile;
}
// 等待验证完成
if (_steps == ESteps.CheckVerifyTempFile)
{
// 注意:同步解压文件更新
_verifyOperation.InternalOnUpdate();
if (_verifyOperation.IsDone == false)
return;
if (_verifyOperation.Status == EOperationStatus.Succeed)
{
if (_fileSystem.WriteFile(Bundle, _fileSavePath))
{
Status = EOperationStatus.Succeed;
_steps = ESteps.Done;
}
else
{
Error = $"{_fileSystem.GetType().FullName} write file failed !";
Status = EOperationStatus.Failed;
_steps = ESteps.Done;
YooLogger.Error(Error);
}
}
else
{
Error = _verifyOperation.Error;
_steps = ESteps.TryAgain;
}
// 注意:验证完成后直接删除文件
if (File.Exists(_fileSavePath))
File.Delete(_fileSavePath);
}
// 重新尝试下载
if (_steps == ESteps.TryAgain)
{
if (FailedTryAgain <= 0)
{
Status = EOperationStatus.Failed;
_steps = ESteps.Done;
YooLogger.Error(Error);
return;
}
_tryAgainTimer += Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
FailedTryAgain--;
_steps = ESteps.CreateRequest;
YooLogger.Warning(Error);
}
}
}
internal override void InternalOnAbort()
{
_steps = ESteps.Done;
DisposeWebRequest();
}
public override void WaitForAsyncComplete()
{
while (true)
{
// 文件验证
if (_verifyOperation != null)
{
if (_verifyOperation.IsDone == false)
_verifyOperation.WaitForAsyncComplete();
}
// 驱动流程
InternalOnUpdate();
// 完成后退出
if (IsDone)
break;
}
}
private void CreateWebRequest()
{
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
DownloadHandlerFile handler = new DownloadHandlerFile(_fileSavePath);
handler.removeFileOnAbort = true;
_webRequest.downloadHandler = handler;
_webRequest.disposeDownloadHandlerOnDispose = true;
_webRequest.SendWebRequest();
}
private void DisposeWebRequest()
{
if (_webRequest != null)
{
//注意引擎底层会自动调用Abort方法
_webRequest.Dispose();
_webRequest = null;
}
}
}
internal sealed class DCFSDownloadResumeFileOperation : DefaultDownloadFileOperation
{
private readonly DefaultCacheFileSystem _fileSystem;
private DownloadHandlerFileRange _downloadHandle;
private VerifyTempFileOperation _verifyOperation;
private long _fileOriginLength = 0;
private string _fileSavePath;
private ESteps _steps = ESteps.None;
internal DCFSDownloadResumeFileOperation(DefaultCacheFileSystem fileSystem, PackageBundle bundle, string mainURL, string fallbackURL, int failedTryAgain, int timeout)
: base(bundle, mainURL, fallbackURL, failedTryAgain, timeout)
{
_fileSystem = fileSystem;
}
internal override void InternalOnStart()
{
_fileSavePath = _fileSystem.GetTempFilePath(Bundle);
// 注意:检测文件是否存在
if (_fileSystem.Exists(Bundle))
{
_steps = ESteps.Done;
Status = EOperationStatus.Succeed;
}
else
{
_steps = ESteps.CreateRequest;
}
}
internal override void InternalOnUpdate()
{
if (_steps == ESteps.None || _steps == ESteps.Done)
return;
// 创建下载器
if (_steps == ESteps.CreateRequest)
{
FileUtility.CreateFileDirectory(_fileSavePath);
// 获取请求地址
_requestURL = GetRequestURL();
// 重置变量
_isAbort = false;
_latestDownloadBytes = 0;
_latestDownloadRealtime = Time.realtimeSinceStartup;
_fileOriginLength = 0;
DownloadProgress = 0f;
DownloadedBytes = 0;
// 重置计时器
if (_tryAgainTimer > 0f)
YooLogger.Warning($"Try again download : {_requestURL}");
_tryAgainTimer = 0f;
// 获取下载起始位置
long fileBeginLength = -1;
if (File.Exists(_fileSavePath))
{
FileInfo fileInfo = new FileInfo(_fileSavePath);
fileBeginLength = fileInfo.Length;
_fileOriginLength = fileBeginLength;
DownloadedBytes = _fileOriginLength;
}
// 检测下载起始位置
if (fileBeginLength >= Bundle.FileSize)
{
// 删除临时文件
if (File.Exists(_fileSavePath))
File.Delete(_fileSavePath);
}
// 创建下载器
CreateWebRequest(fileBeginLength);
_steps = ESteps.CheckRequest;
}
// 检测下载结果
if (_steps == ESteps.CheckRequest)
{
DownloadProgress = _webRequest.downloadProgress;
DownloadedBytes = _fileOriginLength + (long)_webRequest.downloadedBytes;
if (_webRequest.isDone == false)
{
CheckRequestTimeout();
return;
}
// 检查网络错误
if (CheckRequestResult())
_steps = ESteps.VerifyTempFile;
else
_steps = ESteps.TryAgain;
// 在遇到特殊错误的时候删除文件
ClearTempFileWhenError();
// 注意:最终释放请求器
DisposeWebRequest();
}
// 验证下载文件
if (_steps == ESteps.VerifyTempFile)
{
var element = new TempFileElement(_fileSavePath, Bundle.FileCRC, Bundle.FileSize);
_verifyOperation = new VerifyTempFileOperation(element);
OperationSystem.StartOperation(_fileSystem.PackageName, _verifyOperation);
_steps = ESteps.CheckVerifyTempFile;
}
// 等待验证完成
if (_steps == ESteps.CheckVerifyTempFile)
{
if (_verifyOperation.IsDone == false)
return;
if (_verifyOperation.Status == EOperationStatus.Succeed)
{
if (_fileSystem.WriteFile(Bundle, _fileSavePath))
{
Status = EOperationStatus.Succeed;
_steps = ESteps.Done;
}
else
{
Error = $"{_fileSystem.GetType().FullName} write file failed : {_fileSavePath}";
Status = EOperationStatus.Failed;
_steps = ESteps.Done;
}
}
else
{
Error = _verifyOperation.Error;
_steps = ESteps.TryAgain;
}
// 注意:验证完成后直接删除文件
if (File.Exists(_fileSavePath))
File.Delete(_fileSavePath);
}
// 重新尝试下载
if (_steps == ESteps.TryAgain)
{
if (FailedTryAgain <= 0)
{
Status = EOperationStatus.Failed;
_steps = ESteps.Done;
YooLogger.Error(Error);
return;
}
_tryAgainTimer += Time.unscaledDeltaTime;
if (_tryAgainTimer > 1f)
{
FailedTryAgain--;
_steps = ESteps.CreateRequest;
YooLogger.Warning(Error);
}
}
}
internal override void InternalOnAbort()
{
_steps = ESteps.Done;
DisposeWebRequest();
}
public override void WaitForAsyncComplete()
{
while (true)
{
// 文件验证
if (_verifyOperation != null)
{
if (_verifyOperation.IsDone == false)
_verifyOperation.WaitForAsyncComplete();
}
// 驱动流程
InternalOnUpdate();
// 完成后退出
if (IsDone)
break;
}
}
private void CreateWebRequest(long beginLength)
{
_webRequest = DownloadSystemHelper.NewUnityWebRequestGet(_requestURL);
#if UNITY_2019_4_OR_NEWER
var handler = new DownloadHandlerFile(_fileSavePath, true);
handler.removeFileOnAbort = false;
#else
var handler = new DownloadHandlerFileRange(FileSavePath, Bundle.FileSize, _webRequest);
_downloadHandle = handler;
#endif
_webRequest.downloadHandler = handler;
_webRequest.disposeDownloadHandlerOnDispose = true;
if (beginLength > 0)
_webRequest.SetRequestHeader("Range", $"bytes={beginLength}-");
_webRequest.SendWebRequest();
}
private void DisposeWebRequest()
{
if (_downloadHandle != null)
{
_downloadHandle.Cleanup();
_downloadHandle = null;
}
if (_webRequest != null)
{
//注意引擎底层会自动调用Abort方法
_webRequest.Dispose();
_webRequest = null;
}
}
private void ClearTempFileWhenError()
{
if (_fileSystem.ResumeDownloadResponseCodes == null)
return;
//说明:如果遇到以下错误返回码,验证失败直接删除文件
if (_fileSystem.ResumeDownloadResponseCodes.Contains(HttpCode))
{
if (File.Exists(_fileSavePath))
File.Delete(_fileSavePath);
}
}
}
}