说明
批量传输文件是在基础传输之上做的扩展功能。
使用
第一个int类参数表示同时进行的任务数量。其他参数和常规一样。
其中FileRequest、FileOperator、Metadata数量必须相等,即使Metadata为null。
static void TestMultiple(){TcpTouchRpcClient fileClient = CreateTcpTouchRpcClient();Console.WriteLine("请输入文件夹路径");string[] paths = System.IO.Directory.GetFiles(Console.ReadLine(), "*.*", System.IO.SearchOption.AllDirectories);Console.WriteLine($"共搜索到{paths.Length}个文件,按任意键开始传输。");Console.ReadKey();List<FileRequest> requests = new List<FileRequest>();List<FileOperator> fileOperators = new List<FileOperator>();List<Metadata> metadatas = new List<Metadata>();foreach (var item in paths){FileRequest fileRequest = new FileRequest(){Path = item,Overwrite = true,SavePath = item//此处随便写,服务器会重定向保存路径。};metadatas.Add(null);fileOperators.Add(new FileOperator());requests.Add(fileRequest);}int num = 0;LoopAction loopAction = LoopAction.CreateLoopAction(-1,1000,(loop)=>{bool fin = true;var ops = fileOperators.ToArray();foreach (var item in ops){if (item.Result.ResultCode == ResultCode.Default){fin = false;}else{Console.WriteLine($"{++num}号文件传输完成,{item.Result}");fileOperators.Remove(item);}}if (fin){loop.Dispose();Console.WriteLine("传输结束。");}});loopAction.RunAsync();fileClient.PushFilesAsync(10,requests.ToArray(),fileOperators.ToArray(),metadatas.ToArray());Console.ReadKey();}
原理解析
批量传输文件,其实是对单个传输的封装,封装详情请见源码。下列展示PushFiles的源码,并对其做一些解释。
当一个文件结束传输(不一定完成)时,会停顿100ms,然后再继续下个传输,这是因为涉及IO,操作系统和磁盘都不是绝对即时的,如果相邻时间太短,则容易出现问题。当然大家也可以重新按自己意愿封装。
/// <summary>/// 批量推送文件/// </summary>/// <param name="client">终端</param>/// <param name="multipleCount">并行数量</param>/// <param name="fileRequests">批量请求头</param>/// <param name="fileOperators">批量操作器</param>/// <param name="metadatas">批量元数据</param>public static void PushFiles(this IFileClientBase client, int multipleCount, FileRequest[] fileRequests, FileOperator[] fileOperators, Metadata[] metadatas){if (multipleCount < 1){throw new RRQMException("并行数量不能小于1。");}if (fileRequests is null){throw new ArgumentNullException(nameof(fileRequests));}if (fileOperators is null){throw new ArgumentNullException(nameof(fileOperators));}if (!(fileRequests.Length == fileOperators.Length && metadatas.Length == fileOperators.Length)){throw new RRQMException("FileRequest、FileOperator和Metadata数量必须一致。");}int index = 0;int t = 0;int complatedLen = 0;List<Task<Result>> results = new List<Task<Result>>();LoopAction loopAction = LoopAction.CreateLoopAction(-1, 100, (loop) =>{int st = multipleCount - t;for (int i = 0; i < st; i++){if (index == fileRequests.Length){break;}Task<Result> result = client.PushFileAsync(fileRequests[index], fileOperators[index], metadatas[index]);results.Add(result);index++;t++;}List<Task<Result>> cr = new List<Task<Result>>();foreach (var item in results){if (item.IsCompleted){cr.Add(item);t--;complatedLen++;if (complatedLen == fileRequests.Length){loop.Dispose();}}}foreach (var item in cr){results.Remove(item);}});loopAction.Run();}
