web-dev-qa-db-ja.com

C#でSSH.NET SFTPを使用してディレクトリをダウンロードする

Renci.SSHとC#を使用して、WindowsマシンからUnixサーバーに接続しています。ディレクトリの内容がファイルのみの場合、コードは期待どおりに動作しますが、ディレクトリにフォルダが含まれている場合、これが表示されます

Renci.SshNet.Common.SshException: '失敗'

これは私のコードですが、ディレクトリをダウンロードするためにこれを更新するにはどうすればよいですか(存在する場合)

private static void DownloadFile(string arc, string username, string password)
{
    string fullpath;
    string fp;
    var options = new ProgressBarOptions
    {
        ProgressCharacter = '.',
        ProgressBarOnBottom = true
    };

    using (var sftp = new SftpClient(Host, username, password))
    {
        sftp.Connect();
        fp = RemoteDir + "/" + arc;
        if (sftp.Exists(fp))     
            fullpath = fp;
        else
            fullpath = SecondaryRemoteDir + d + "/" + arc;

        if (sftp.Exists(fullpath))
        {
            var files = sftp.ListDirectory(fullpath);
            foreach (var file in files)
            {
                if (file.Name.ToLower().Substring(0, 1) != ".")
                {
                    Console.WriteLine("Downloading file from the server...");
                    Console.WriteLine();
                    using (var pbar = new ProgressBar(100, "Downloading " + file.Name + "....", options))
                    {
                        SftpFileAttributes att = sftp.GetAttributes(fullpath + "/" + file.Name);
                        var fileSize = att.Size;
                        var ms = new MemoryStream();
                        IAsyncResult asyncr = sftp.BeginDownloadFile(fullpath + "/" + file.Name, ms);
                        SftpDownloadAsyncResult sftpAsyncr = (SftpDownloadAsyncResult)asyncr;
                        int lastpct = 0;
                        while (!sftpAsyncr.IsCompleted)
                        {
                            int pct = (int)((long)sftpAsyncr.DownloadedBytes / fileSize) * 100;
                            if (pct > lastpct)
                                for (int i = 1; i < pct - lastpct; i++)
                                    pbar.Tick();
                        }
                        sftp.EndDownloadFile(asyncr);
                        Console.WriteLine("Writing File to disk...");
                        Console.WriteLine();
                        string localFilePath = "C:\" + file.Name;
                        var fs = new FileStream(localFilePath, FileMode.Create, FileAccess.Write);
                        ms.WriteTo(fs);
                        fs.Close();
                        ms.Close();
                    }
                }
            }
        }
        else
        {
            Console.WriteLine("The arc " + arc + " does not exist");
            Console.WriteLine();
            Console.WriteLine("Please press any key to close this window");
            Console.ReadKey();
        }
    }
}
3
BandaidMan

BeginDownloadFileは、ファイルをダウンロードします。フォルダーのダウンロードには使用できません。そのためには、含まれているファイルを1つずつダウンロードする必要があります。

次の例では、簡単にするために同期ダウンロード(DownloadFileではなくBeginDownloadFile)を使用しています。結局のところ、非同期ダウンロードが完了するまで同期的に待機しています。同期ダウンロードでプログレスバーを実装するには、 SSH.NETを使用したProgressBarでのファイルダウンロードの進行状況の表示 を参照してください。

public static void DownloadDirectory(
    SftpClient sftpClient, string sourceRemotePath, string destLocalPath)
{
    Directory.CreateDirectory(destLocalPath);
    IEnumerable<SftpFile> files = sftpClient.ListDirectory(sourceRemotePath);
    foreach (SftpFile file in files)
    {
        if ((file.Name != ".") && (file.Name != ".."))
        {
            string sourceFilePath = sourceRemotePath + "/" + file.Name;
            string destFilePath = Path.Combine(destLocalPath, file.Name);
            if (file.IsDirectory)
            {
                DownloadDirectory(sftpClient, sourceFilePath, destFilePath);
            }
            else
            {
                using (Stream fileStream = File.Create(destFilePath))
                {
                    sftpClient.DownloadFile(sourceFilePath, fileStream);
                }
            }
        }
    }
}
5
Martin Prikryl