FileDownloader.cs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. using System;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using System.IO;
  5. using UnityEngine;
  6. namespace YooAsset
  7. {
  8. /// <summary>
  9. /// 文件下载器
  10. /// </summary>
  11. internal sealed class FileDownloader : DownloaderBase
  12. {
  13. private enum ESteps
  14. {
  15. None,
  16. PrepareDownload,
  17. CreateDownloader,
  18. CheckDownload,
  19. VerifyTempFile,
  20. WaitingVerifyTempFile,
  21. CachingFile,
  22. TryAgain,
  23. Done,
  24. }
  25. private VerifyTempFileOperation _verifyFileOp = null;
  26. private ESteps _steps = ESteps.None;
  27. public FileDownloader(BundleInfo bundleInfo, System.Type requesterType, int failedTryAgain, int timeout) : base(bundleInfo, requesterType, failedTryAgain, timeout)
  28. {
  29. }
  30. public override void SendRequest(params object[] args)
  31. {
  32. if (_steps == ESteps.None)
  33. {
  34. _steps = ESteps.PrepareDownload;
  35. }
  36. }
  37. public override void Update()
  38. {
  39. if (_steps == ESteps.None)
  40. return;
  41. if (IsDone())
  42. return;
  43. // 准备下载
  44. if (_steps == ESteps.PrepareDownload)
  45. {
  46. // 获取请求地址
  47. _requestURL = GetRequestURL();
  48. // 重置变量
  49. DownloadProgress = 0f;
  50. DownloadedBytes = 0;
  51. // 重置变量
  52. _isAbort = false;
  53. _latestDownloadBytes = 0;
  54. _latestDownloadRealtime = Time.realtimeSinceStartup;
  55. // 重置计时器
  56. if (_tryAgainTimer > 0f)
  57. YooLogger.Warning($"Try again download : {_requestURL}");
  58. _tryAgainTimer = 0f;
  59. _steps = ESteps.CreateDownloader;
  60. }
  61. // 创建下载器
  62. if (_steps == ESteps.CreateDownloader)
  63. {
  64. _requester = (IWebRequester)Activator.CreateInstance(_requesterType);
  65. _requester.Create(_requestURL, _bundleInfo);
  66. _steps = ESteps.CheckDownload;
  67. }
  68. // 检测下载结果
  69. if (_steps == ESteps.CheckDownload)
  70. {
  71. _requester.Update();
  72. DownloadedBytes = _requester.DownloadedBytes;
  73. DownloadProgress = _requester.DownloadProgress;
  74. if (_requester.IsDone() == false)
  75. {
  76. CheckTimeout();
  77. return;
  78. }
  79. _lastestNetError = _requester.RequestNetError;
  80. _lastestHttpCode = _requester.RequestHttpCode;
  81. if (_requester.Status != ERequestStatus.Success)
  82. {
  83. _steps = ESteps.TryAgain;
  84. }
  85. else
  86. {
  87. _steps = ESteps.VerifyTempFile;
  88. }
  89. }
  90. // 验证下载文件
  91. if (_steps == ESteps.VerifyTempFile)
  92. {
  93. VerifyTempFileElement element = new VerifyTempFileElement(_bundleInfo.TempDataFilePath, _bundleInfo.Bundle.FileCRC, _bundleInfo.Bundle.FileSize);
  94. _verifyFileOp = VerifyTempFileOperation.CreateOperation(element);
  95. OperationSystem.StartOperation(_bundleInfo.Bundle.PackageName, _verifyFileOp);
  96. _steps = ESteps.WaitingVerifyTempFile;
  97. }
  98. // 等待验证完成
  99. if (_steps == ESteps.WaitingVerifyTempFile)
  100. {
  101. if (WaitForAsyncComplete)
  102. _verifyFileOp.InternalOnUpdate();
  103. if (_verifyFileOp.IsDone == false)
  104. return;
  105. if (_verifyFileOp.Status == EOperationStatus.Succeed)
  106. {
  107. _steps = ESteps.CachingFile;
  108. }
  109. else
  110. {
  111. string tempFilePath = _bundleInfo.TempDataFilePath;
  112. if (File.Exists(tempFilePath))
  113. File.Delete(tempFilePath);
  114. _lastestNetError = _verifyFileOp.Error;
  115. _steps = ESteps.TryAgain;
  116. }
  117. }
  118. // 缓存下载文件
  119. if (_steps == ESteps.CachingFile)
  120. {
  121. try
  122. {
  123. CachingFile();
  124. _status = EStatus.Succeed;
  125. _steps = ESteps.Done;
  126. }
  127. catch (Exception e)
  128. {
  129. _lastestNetError = e.Message;
  130. _steps = ESteps.TryAgain;
  131. }
  132. }
  133. // 重新尝试下载
  134. if (_steps == ESteps.TryAgain)
  135. {
  136. if (_failedTryAgain <= 0)
  137. {
  138. ReportError();
  139. _status = EStatus.Failed;
  140. _steps = ESteps.Done;
  141. return;
  142. }
  143. _tryAgainTimer += Time.unscaledDeltaTime;
  144. if (_tryAgainTimer > 1f)
  145. {
  146. _failedTryAgain--;
  147. _steps = ESteps.PrepareDownload;
  148. ReportWarning();
  149. }
  150. }
  151. }
  152. public override void Abort()
  153. {
  154. if (_requester != null)
  155. _requester.Abort();
  156. if (IsDone() == false)
  157. {
  158. _status = EStatus.Failed;
  159. _steps = ESteps.Done;
  160. _lastestNetError = "user abort";
  161. _lastestHttpCode = 0;
  162. }
  163. }
  164. public override AssetBundle GetAssetBundle()
  165. {
  166. throw new NotImplementedException();
  167. }
  168. /// <summary>
  169. /// 缓存下载文件
  170. /// </summary>
  171. private void CachingFile()
  172. {
  173. string tempFilePath = _bundleInfo.TempDataFilePath;
  174. string infoFilePath = _bundleInfo.CachedInfoFilePath;
  175. string dataFilePath = _bundleInfo.CachedDataFilePath;
  176. string dataFileCRC = _bundleInfo.Bundle.FileCRC;
  177. long dataFileSize = _bundleInfo.Bundle.FileSize;
  178. if (File.Exists(infoFilePath))
  179. File.Delete(infoFilePath);
  180. if (File.Exists(dataFilePath))
  181. File.Delete(dataFilePath);
  182. // 移动临时文件路径
  183. FileInfo fileInfo = new FileInfo(tempFilePath);
  184. fileInfo.MoveTo(dataFilePath);
  185. // 写入信息文件记录验证数据
  186. CacheFileInfo.WriteInfoToFile(infoFilePath, dataFileCRC, dataFileSize);
  187. // 记录缓存文件
  188. _bundleInfo.CacheRecord();
  189. }
  190. }
  191. }