WinSCP.Net,文件夹未从远程复制到本地

WinSCP.Net, folder is not copied from remote to local

我一直在使用 WinSCP 定期从 Unix 服务器下载文件到 Windows 服务器,并且一直没有问题。我还检查远程文件是否较旧或已经存在(不要复制)。

现在,我必须做同样的事情,但这次我必须下载文件和文件夹。文件复制得很好,但文件夹不是。在玩设置时,我得到它来复制文件夹的内容,但它们被复制到我的本地根文件夹;我以为 WinSCP 会复制所有内容。

在下面的代码中,LocalFolder 是 Z:\My_Data,LogRootFolder 是 /xyz/gtc/a00/

遥控器上的文件夹结构是 /xyz/gtc/a00/ABCD/outcomes/ 子文件夹“备份”,其中有许多子文件夹命名为日期(例如 /xyz/gtc/a00/ABCD/outcomes/backup/2021-06- 23/)

复制“backup/2021-xx-xx/”个文件和文件夹中的none个,或者全部复制到Z:\My_Data\ABCD

设置会话后,调用SFTP_Session:

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();
        };                                                
        //var opts = EnumerationOptions.EnumerateDirectories | EnumerationOptions.AllDirectories;
        //IEnumerable<RemoteFileInfo> fileInfos = SFTP_Session.EnumerateRemoteFiles(sRemotePath, "*.dat", opts);  <-- This copies files in folder(s) to m local root folder
        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 localFilePath = Path.Combine(sLocalFolder, fileInfo.Name);

        if (fileInfo.IsDirectory)
        {
            // Create local subdirectory, if it does not exist yet
            if (!Directory.Exists(localFilePath))
            {
                Directory.CreateDirectory(localFilePath);
            }
        }
        else
        {
            string remoteFilePath = RemotePath.EscapeFileMask(fileInfo.FullName);

            // If file does not exist in local folder, download
            if (!File.Exists(localFilePath))
            {
                bDownload = true;
            }
            else    // If file exists in local folder but is older, download; else skip
            {
                DateTime remoteWriteTime = SFTP_Session.GetFileInfo(remoteFilePath).LastWriteTime;
                DateTime localWriteTime = File.GetLastWriteTime(localFilePath);

                if (remoteWriteTime > localWriteTime)
                {
                    bDownload = true;
                }
                else
                {
                    bDownload = false;
                }
            }

            if (bDownload)
            {
                // Download file
                TransferOptions oTrRes = new TransferOptions();

                oTrRes.TransferMode = TransferMode.Automatic; //The Transfer Mode - Automatic, Binary, or Ascii 
                oTrRes.FilePermissions = null;  //Permissions applied to remote files; null for default permissions. Can set user, Group, or other Read/Write/Execute permissions.  
                oTrRes.PreserveTimestamp = false;  //Set last write time of destination file to that of source file - basically change the timestamp to match destination and source files.    
                oTrRes.ResumeSupport.State = TransferResumeSupportState.Off;

                TransferOperationResult transferResult = SFTP_Session.GetFiles(remoteFilePath, localFilePath, false, oTrRes);//.Replace("\",""));  // I thought this would get files AND folders
                                
                // Throw on any error
                transferResult.Check();

                foreach (TransferEventArgs transfer in transferResult.Transfers)
                {
                    // Store local file info in a data table for processing later
                    ...
                }
                SessionRemoteExceptionCollection srec = transferResult.Failures;

                foreach (SessionRemoteException sre in srec)
                {
                    // Log errors
                }

                // Did the download succeeded?
                if (!transferResult.IsSuccess)
                {
                    // Log error (but continue with other files)
                }
            }
        }
    }

最后,在本地文件夹中,我看到下载和复制的文件以及我创建的子文件夹(使用上面的代码),但这些文件夹中没有文件。看不到我在这里遗漏了什么。

您的代码基本上是将远程目录同步到本地目录。

无需修复您的代码,您只需调用 Session.SynchronizeDirectories 即可替换大部分代码: https://winscp.net/eng/docs/library_session_synchronizedirectories

首先在 WinSCP GUI 中尝试同步,看看它是否满足您的需要。

  • 如果需要对同步文件做一些处理,使用Session.SynchronizeDirectories返回的SynchronizationResult。它包含所有同步文件的列表。
  • 如果您需要从同步中排除某些文件,请使用TransferOptions.FileMask