说明

批量传输文件是在基础传输之上做的扩展功能。

使用

第一个int类参数表示同时进行的任务数量。其他参数和常规一样。
其中FileRequest、FileOperator、Metadata数量必须相等,即使Metadata为null。

  1. static void TestMultiple()
  2. {
  3. TcpTouchRpcClient fileClient = CreateTcpTouchRpcClient();
  4. Console.WriteLine("请输入文件夹路径");
  5. string[] paths = System.IO.Directory.GetFiles(Console.ReadLine(), "*.*", System.IO.SearchOption.AllDirectories);
  6. Console.WriteLine($"共搜索到{paths.Length}个文件,按任意键开始传输。");
  7. Console.ReadKey();
  8. List<FileRequest> requests = new List<FileRequest>();
  9. List<FileOperator> fileOperators = new List<FileOperator>();
  10. List<Metadata> metadatas = new List<Metadata>();
  11. foreach (var item in paths)
  12. {
  13. FileRequest fileRequest = new FileRequest()
  14. {
  15. Path = item,
  16. Overwrite = true,
  17. SavePath = item//此处随便写,服务器会重定向保存路径。
  18. };
  19. metadatas.Add(null);
  20. fileOperators.Add(new FileOperator());
  21. requests.Add(fileRequest);
  22. }
  23. int num = 0;
  24. LoopAction loopAction = LoopAction.CreateLoopAction(-1,1000,(loop)=>
  25. {
  26. bool fin = true;
  27. var ops = fileOperators.ToArray();
  28. foreach (var item in ops)
  29. {
  30. if (item.Result.ResultCode == ResultCode.Default)
  31. {
  32. fin = false;
  33. }
  34. else
  35. {
  36. Console.WriteLine($"{++num}号文件传输完成,{item.Result}");
  37. fileOperators.Remove(item);
  38. }
  39. }
  40. if (fin)
  41. {
  42. loop.Dispose();
  43. Console.WriteLine("传输结束。");
  44. }
  45. });
  46. loopAction.RunAsync();
  47. fileClient.PushFilesAsync(10,requests.ToArray(),fileOperators.ToArray(),metadatas.ToArray());
  48. Console.ReadKey();
  49. }

原理解析

批量传输文件,其实是对单个传输的封装,封装详情请见源码。下列展示PushFiles的源码,并对其做一些解释。

当一个文件结束传输(不一定完成)时,会停顿100ms,然后再继续下个传输,这是因为涉及IO,操作系统和磁盘都不是绝对即时的,如果相邻时间太短,则容易出现问题。当然大家也可以重新按自己意愿封装。

  1. /// <summary>
  2. /// 批量推送文件
  3. /// </summary>
  4. /// <param name="client">终端</param>
  5. /// <param name="multipleCount">并行数量</param>
  6. /// <param name="fileRequests">批量请求头</param>
  7. /// <param name="fileOperators">批量操作器</param>
  8. /// <param name="metadatas">批量元数据</param>
  9. public static void PushFiles(this IFileClientBase client, int multipleCount, FileRequest[] fileRequests, FileOperator[] fileOperators, Metadata[] metadatas)
  10. {
  11. if (multipleCount < 1)
  12. {
  13. throw new RRQMException("并行数量不能小于1。");
  14. }
  15. if (fileRequests is null)
  16. {
  17. throw new ArgumentNullException(nameof(fileRequests));
  18. }
  19. if (fileOperators is null)
  20. {
  21. throw new ArgumentNullException(nameof(fileOperators));
  22. }
  23. if (!(fileRequests.Length == fileOperators.Length && metadatas.Length == fileOperators.Length))
  24. {
  25. throw new RRQMException("FileRequest、FileOperator和Metadata数量必须一致。");
  26. }
  27. int index = 0;
  28. int t = 0;
  29. int complatedLen = 0;
  30. List<Task<Result>> results = new List<Task<Result>>();
  31. LoopAction loopAction = LoopAction.CreateLoopAction(-1, 100, (loop) =>
  32. {
  33. int st = multipleCount - t;
  34. for (int i = 0; i < st; i++)
  35. {
  36. if (index == fileRequests.Length)
  37. {
  38. break;
  39. }
  40. Task<Result> result = client.PushFileAsync(fileRequests[index], fileOperators[index], metadatas[index]);
  41. results.Add(result);
  42. index++;
  43. t++;
  44. }
  45. List<Task<Result>> cr = new List<Task<Result>>();
  46. foreach (var item in results)
  47. {
  48. if (item.IsCompleted)
  49. {
  50. cr.Add(item);
  51. t--;
  52. complatedLen++;
  53. if (complatedLen == fileRequests.Length)
  54. {
  55. loop.Dispose();
  56. }
  57. }
  58. }
  59. foreach (var item in cr)
  60. {
  61. results.Remove(item);
  62. }
  63. });
  64. loopAction.Run();
  65. }