DownloadHelper.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. using Vinno.IUS.Common.IO;
  8. using Vinno.IUS.Common.Log;
  9. using Vinno.IUS.Common.Network.Leaf;
  10. using Vinno.vCloud.Common.Storage.ObjectStorageInfo;
  11. using Vinno.vCloud.Protocol.Infrastructures;
  12. namespace Vinno.vCloud.Common.Storage.Download
  13. {
  14. public class DownloadHelper
  15. {
  16. private static Dictionary<StorageType, IDownloader> _storagers;
  17. private static readonly object progressLock = new object();
  18. static DownloadHelper()
  19. {
  20. _storagers = new Dictionary<StorageType, IDownloader>();
  21. _storagers.Add(StorageType.Default, new VCloudStorageDownloader());
  22. _storagers.Add(StorageType.ObjectStorage, new ObjectStorageDownloader());
  23. }
  24. /// <summary>
  25. /// download file(Breakpoint continuingly)
  26. /// if the file size is less than 4M return byteBuffer ,else return FileBuffer
  27. /// </summary>
  28. /// <param name="creator"></param>
  29. /// <param name="fileToken"></param>
  30. /// <param name="progress"></param>
  31. /// <param name="cancelTokenSource"></param>
  32. /// <param name="timeout"></param>
  33. /// <returns></returns>
  34. public static IBuffer GetFile(string fileToken,string fileCacchePath = "", Action<double> progress = null,
  35. CancellationTokenSource cancelTokenSource = null, int timeout = 0)
  36. {
  37. try
  38. {
  39. // Logger.WriteLineInfo($"Get file buffer done with file token:{fileToken}");
  40. var tokenInfo = new FileTokenInfo(fileToken);
  41. var result = _storagers[tokenInfo.StorageType].GetFile(tokenInfo, fileCacchePath, progress, cancelTokenSource, timeout);
  42. // Logger.WriteLineInfo($"Get file buffer with file token done");
  43. return result;
  44. }
  45. catch (Exception ex)
  46. {
  47. Logger.WriteLineError($"GetFile Exception:{ex}");
  48. return null;
  49. }
  50. }
  51. /// <summary>
  52. /// Get file from storage (Vinno storage or ufile)
  53. /// </summary>
  54. /// <param name="fileToken"></param>
  55. /// <param name="filePath">download file to fileth</param>
  56. /// <param name="progress"></param>
  57. /// <param name="cancelTokenSource"></param>
  58. public static void GetFile(string fileToken, string filePath, Action<double> progress = null, CancellationTokenSource cancelTokenSource = null,bool isUseCDNNode = true)
  59. {
  60. try
  61. {
  62. //Logger.WriteLineInfo($"Get file done with file token:{fileToken}");
  63. var tokenInfo = new FileTokenInfo(fileToken);
  64. _storagers[tokenInfo.StorageType].GetFile(tokenInfo, filePath, progress, cancelTokenSource, isUseCDNNode);
  65. }
  66. catch (Exception ex)
  67. {
  68. Logger.WriteLineError($"GetFile Exception:{ex}");
  69. }
  70. }
  71. /// <summary>
  72. /// download large file by file tokens
  73. /// </summary>
  74. /// <param name="tokens"></param>
  75. /// <param name="filePath"></param>
  76. /// <param name="progress"></param>
  77. /// <param name="cancelTokenSource">每次必须是新的</param>
  78. /// <param name="isUseCDNNode"></param>
  79. public static void GetLargeFile(IList<string> tokens,string filePath, Action<double> progress = null, CancellationTokenSource cancelTokenSource = null, bool isUseCDNNode = true)
  80. {
  81. var files = new List<string>();
  82. progress.Invoke(0.0001);
  83. var count = tokens.Count;
  84. var totalCount = count;
  85. tokens.AsParallel().WithDegreeOfParallelism(5).ForAll((token) =>
  86. {
  87. if (cancelTokenSource != null && cancelTokenSource.IsCancellationRequested)
  88. {
  89. return;
  90. }
  91. var tokenInfo = new FileTokenInfo(token);
  92. var floder = Path.GetDirectoryName(filePath);
  93. var fileName = token.Substring(token.LastIndexOf('/') + 1);
  94. var path = Path.Combine(floder, fileName);
  95. var isNeedWrite = false;
  96. if (File.Exists(path))
  97. {
  98. using (FileStream tempStream = new FileStream(path, FileMode.OpenOrCreate))
  99. {
  100. if (tempStream.Length == 0)
  101. {
  102. isNeedWrite = true;
  103. }
  104. }
  105. }
  106. if (!File.Exists(path) || isNeedWrite)
  107. {
  108. _storagers[tokenInfo.StorageType].GetFile(tokenInfo, path, null, cancelTokenSource, isUseCDNNode);
  109. }
  110. if (cancelTokenSource != null && cancelTokenSource.IsCancellationRequested)
  111. {
  112. progress.Invoke(0.0);
  113. return;
  114. }
  115. files.Add(path);
  116. lock (progressLock)
  117. {
  118. totalCount--;
  119. progress.Invoke((double)(count - totalCount) / count * 0.9);
  120. }
  121. });
  122. if (cancelTokenSource != null && cancelTokenSource.IsCancellationRequested)
  123. {
  124. progress.Invoke(0.0);
  125. return;
  126. }
  127. var result = CombineFiles(files, filePath, progress);
  128. if (result)
  129. {
  130. progress.Invoke(1.0);
  131. ClearFiles(files);
  132. }
  133. }
  134. /// <summary>
  135. /// Get File Async
  136. /// </summary>
  137. /// <param name="creator"></param>
  138. /// <param name="fileToken"></param>
  139. /// <param name="filePath"></param>
  140. /// <param name="progress"></param>
  141. /// <param name="cancelTokenSource"></param>
  142. public static async Task GetFileAsync(string fileToken, string filePath,
  143. Action<double> progress = null, CancellationTokenSource cancelTokenSource = null)
  144. {
  145. try
  146. {
  147. // Logger.WriteLineInfo($"Async get file done with file token:{fileToken}");
  148. var tokenInfo = new FileTokenInfo(fileToken);
  149. await _storagers[tokenInfo.StorageType].GetFileAsync(tokenInfo, filePath, progress, cancelTokenSource);
  150. }
  151. catch (Exception ex)
  152. {
  153. Logger.WriteLineError($"GetFileAsync Exception:{ex}");
  154. }
  155. }
  156. /// <summary>
  157. /// Get File Async
  158. /// </summary>
  159. /// <param name="creator"></param>
  160. /// <param name="fileToken"></param>
  161. /// <param name="filePath"></param>
  162. /// <param name="progress"></param>
  163. /// <param name="cancelTokenSource"></param>
  164. public static async Task<IBuffer> GetFileAsync(string fileToken, string cacheFilePath,
  165. Action<double> progress = null, CancellationTokenSource cancelTokenSource = null,int timeout = 0)
  166. {
  167. try
  168. {
  169. Logger.WriteLineInfo($"Async get file buffer done with file token:{fileToken}");
  170. var tokenInfo = new FileTokenInfo(fileToken);
  171. var result = await _storagers[tokenInfo.StorageType].GetFileAsync(tokenInfo, cacheFilePath, progress, cancelTokenSource, timeout);
  172. return result;
  173. }
  174. catch (Exception ex)
  175. {
  176. Logger.WriteLineError($"GetFileAsync Exception:{ex}");
  177. return null;
  178. }
  179. }
  180. /// <summary>
  181. /// 批量获取文件
  182. /// </summary>
  183. /// <param name="creator">TCPCreator,UFile时不用传</param>
  184. /// <param name="fileTokens">文件Token列表</param>
  185. /// <param name="progress">进度回调</param>
  186. /// <param name="cancelTokenSource">取消标识,UFile时不可取消</param>
  187. /// <returns>文件内容列表</returns>
  188. public static IEnumerable<byte[]> GetFiles(IList<string> fileTokens,
  189. CancellationTokenSource cancelTokenSource = null, ClientLeaf storageLeaf = null)
  190. {
  191. try
  192. {
  193. var stroageType = StorageType.Default;
  194. var fileTokenList = new List<FileTokenInfo>();
  195. foreach (var token in fileTokens)
  196. {
  197. var tokenInfo = new FileTokenInfo(token);
  198. stroageType = tokenInfo.StorageType;
  199. fileTokenList.Add(tokenInfo);
  200. }
  201. return _storagers[stroageType].GetFiles(fileTokenList, cancelTokenSource, storageLeaf);
  202. }
  203. catch (Exception ex)
  204. {
  205. Logger.WriteLineError($"GetFiles Exception:{ex}");
  206. return null;
  207. }
  208. }
  209. /// <summary>
  210. /// download file(Breakpoint continuingly)
  211. /// if the file size is less than 4M return byteBuffer ,else return FileBuffer
  212. /// </summary>
  213. /// <param name="creator"></param>
  214. /// <param name="fileToken"></param>
  215. /// <param name="from"></param>
  216. /// <param name="to"></param>IE
  217. /// <param name="progress"></param>
  218. /// <param name="cancelTokenSource"></param>
  219. /// <param name="timeout"></param>
  220. /// <returns></returns>
  221. public static IBuffer GetFile(string fileToken, string cacheFilePath, long from, long to, Action<double> progress = null,
  222. CancellationTokenSource cancelTokenSource = null, int timeout = 0)
  223. {
  224. try
  225. {
  226. Logger.WriteLineInfo($"Get file2 buffer done with file token:{fileToken}");
  227. var tokenInfo = new FileTokenInfo(fileToken);
  228. var stroageType = tokenInfo.StorageType;
  229. var result = _storagers[stroageType].GetFile(tokenInfo, cacheFilePath, from, to, progress, cancelTokenSource, timeout);
  230. return result;
  231. }
  232. catch (Exception ex)
  233. {
  234. Logger.WriteLineError($"GetFile Exception:{ex}");
  235. return null;
  236. }
  237. }
  238. /// <summary>
  239. /// 获取更新文件(批量)
  240. /// </summary>
  241. /// <param name="tempFolder"></param>
  242. /// <param name="upgradeType"></param>
  243. /// <param name="currentVersion"></param>
  244. /// <returns></returns>
  245. public static bool DownloadFiles(string tempFolder, List<ObjectFileInfo> fileList, Action<double> progressCallback)
  246. {
  247. try
  248. {
  249. return _storagers[StorageType.ObjectStorage].DownloadFiles(tempFolder, fileList, progressCallback);
  250. }
  251. catch (Exception ex)
  252. {
  253. Logger.WriteLineError($"DownloadFiles Exception:{ex}");
  254. return false;
  255. }
  256. }
  257. /// <summary>
  258. /// 合并文件
  259. /// </summary>
  260. /// <param name="filePaths">要合并的文件列表</param>
  261. /// <param name="combineFile">合并后的文件路径带文件名</param>
  262. static bool CombineFiles(List<string> filePaths, string combineFile, Action<double> progress = null)
  263. {
  264. try
  265. {
  266. var fileDictionary = new Dictionary<int, string>();
  267. foreach (var f in filePaths)
  268. {
  269. if (int.TryParse(f.Substring(f.LastIndexOf("part") + 4), out int key))
  270. {
  271. fileDictionary.Add(key, f);
  272. }
  273. else
  274. {
  275. Logger.WriteLineError($"TryParse part error in {f}");
  276. return false;
  277. }
  278. }
  279. var count = filePaths.Count();
  280. var progressValue = 0.0;
  281. using (FileStream CombineStream = new FileStream(combineFile, FileMode.OpenOrCreate))
  282. {
  283. using (BinaryWriter CombineWriter = new BinaryWriter(CombineStream))
  284. {
  285. for (var i = 0; i < count; i++)
  286. {
  287. var file = fileDictionary.FirstOrDefault(x=>x.Key == i).Value;
  288. using (FileStream fileStream = new FileStream(file, FileMode.Open))
  289. {
  290. using (BinaryReader fileReader = new BinaryReader(fileStream))
  291. {
  292. byte[] TempBytes = fileReader.ReadBytes((int)fileStream.Length);
  293. CombineWriter.Write(TempBytes);
  294. }
  295. }
  296. progressValue += 1.0 / count * 0.1;
  297. progress?.Invoke(progressValue + 0.9);
  298. }
  299. return true;
  300. }
  301. }
  302. }
  303. catch (Exception ex)
  304. {
  305. Logger.WriteLineInfo($"CombineFiles exception:{ex}");
  306. return false;
  307. }
  308. }
  309. /// <summary>
  310. /// 批量清理文件
  311. /// </summary>
  312. /// <param name="files"></param>
  313. static void ClearFiles(IList<string> files)
  314. {
  315. Task.Run(() =>
  316. {
  317. try
  318. {
  319. foreach (var f in files)
  320. {
  321. File.Delete(f);
  322. }
  323. }
  324. catch (Exception ex)
  325. {
  326. Logger.WriteLineError($"delete file ex:{ex}");
  327. }
  328. });
  329. }
  330. }
  331. }