WinSCP.Net远程到本地复制时文件夹无法正常保留层级同步问题求助
问题根因
- 本地路径拼接错误:当前仅用
fileInfo.Name拼接本地存储路径,仅保留了文件名,丢失了远程文件相对于根同步目录的层级结构,导致所有文件都被放到目标根目录下。 - 目录创建逻辑未生效:你通过正则
\.(dat|err)$过滤枚举结果,仅匹配后缀为dat/err的文件,目录不会被匹配到,因此fileInfo.IsDirectory的分支永远不会执行,对应子目录不会被提前创建。 - 重复请求冗余:你在判断文件新旧时重复调用
SFTP_Session.GetFileInfo获取远程文件时间,实际上EnumerateRemoteFiles返回的RemoteFileInfo已经自带LastWriteTime属性,无需额外请求服务器。
修复方案
直接修改foreach循环内的路径逻辑,提前自动创建父目录即可,不需要单独枚举处理目录:
string sRemotePath = LogRootFolder + "ABCD/outcomes/"; string sLocalFolder = Path.Combine(LocalFolder, @"ABCD\"); if (SFTP_Session.Opened) { using (SFTP_Session) { SFTP_Session.QueryReceived += (sender, e) => { ... e.Continue(); }; Regex mask = new Regex(@"\.(dat|err)$", RegexOptions.IgnoreCase); IEnumerable<RemoteFileInfo> fileInfos = SFTP_Session.EnumerateRemoteFiles(sRemotePath, null, EnumerationOptions.AllDirectories) .Where(fileInfo => mask.Match(fileInfo.Name).Success) .ToList(); foreach (RemoteFileInfo fileInfo in fileInfos) { // 计算远程文件相对于同步根目录的相对路径 string relativePath = fileInfo.FullName.Substring(sRemotePath.Length).TrimStart('/'); // 转换为Windows路径分隔符 relativePath = relativePath.Replace('/', Path.DirectorySeparatorChar); // 拼接完整本地路径 string localFilePath = Path.Combine(sLocalFolder, relativePath); // 提前创建文件对应的父目录 string localDir = Path.GetDirectoryName(localFilePath); if (!Directory.Exists(localDir)) { Directory.CreateDirectory(localDir); } bool bDownload = false; // 若本地不存在该文件则下载 if (!File.Exists(localFilePath)) { bDownload = true; } else // 若本地文件已存在但比远程文件旧则下载,否则跳过 { // 直接使用枚举返回的时间属性,无需额外请求服务器 DateTime remoteWriteTime = fileInfo.LastWriteTime; DateTime localWriteTime = File.GetLastWriteTime(localFilePath); if (remoteWriteTime > localWriteTime) { bDownload = true; } else { bDownload = false; } } if (bDownload) { // 下载文件 TransferOptions oTrRes = new TransferOptions(); oTrRes.TransferMode = TransferMode.Automatic; oTrRes.FilePermissions = null; oTrRes.PreserveTimestamp = false; oTrRes.ResumeSupport.State = TransferResumeSupportState.Off; string remoteFilePath = RemotePath.EscapeFileMask(fileInfo.FullName); TransferOperationResult transferResult = SFTP_Session.GetFiles(remoteFilePath, localFilePath, false, oTrRes); // 出现任意错误则抛出 transferResult.Check(); foreach (TransferEventArgs transfer in transferResult.Transfers) { // 将本地文件信息存入数据表供后续处理 ... } SessionRemoteExceptionCollection srec = transferResult.Failures; foreach (SessionRemoteException sre in srec) { // 记录错误日志 } // 判断下载是否成功 if (!transferResult.IsSuccess) { // 记录错误日志(继续处理其他文件) } } } } }
修改后远程文件会完整保留层级结构存储到本地,例如远程路径/xyz/gtc/a00/ABCD/outcomes/backup/2021-06-23/a.dat会自动存储到本地路径Z:\My_Data\ABCD\backup\2021-06-23\a.dat。
内容的提问来源于stack exchange,提问作者NoBullMan
相关产品推荐
相关产品推荐

