web-dev-qa-db-ja.com

SSH.NETライブラリを使用してSFTPからファイルをダウンロードする

string Host = @"ftphost";
string username = "user";
string password = "********";
string localFileName  = System.IO.Path.GetFileName(@"localfilename");
string remoteDirectory = "/export/";
using (var sftp = new SftpClient(Host, username, password))
{
    sftp.Connect();
    var files = sftp.ListDirectory(remoteDirectory);
    foreach (var file in files)
    {
        if (!file.Name.StartsWith("."))
        {
            string remoteFileName = file.Name;
            if (file.LastWriteTime.Date == DateTime.Today)

            Console.WriteLine(file.FullName);

            File.OpenWrite(localFileName);

            string sDir = @"localpath";

            Stream file1 = File.OpenRead(remoteDirectory + file.Name);
            sftp.DownloadFile(remoteDirectory, file1);
        }
    }
}

SSH.NETを使用しています(Renci.SshNet)SFTPサーバーで動作するライブラリ。私がする必要があるのは、今日の日付に基づいてSFTPサーバー上の特定のフォルダーからファイルを取得することです。次に、これらのファイルをSFTPサーバーから私のサーバーのローカルドライブにコピーします。

上記は私が持っているコードですが、動作していません。ファイルが存在しないと表示される場合もありますが、ダウンロードするファイルがローカルサーバーにない場合もありますが、その日にリモートフォルダーにアップロードされたファイルをダウンロードする必要があります。

誰かが見て、何が悪いのかを見ることができますか?ストリーム部分に関係があると思います。私は以前に持っていたいくつかのコードを取り、プロセスを逆にすることができると思っていたファイルをアップロードする以外に、FTPで多くの作業をしましたが、それは機能しません。私が使用したコードはこれに基づいています

31
user3195153

SSH.NETライブラリを使用してファイルをダウンロードする簡単な作業コードは次のとおりです。

using (Stream fileStream = File.Create(@"C:\target\local\path\file.Zip"))
{
    sftp.DownloadFile("/source/remote/path/file.Zip", fileStream);
}

C#でSSH.NET SFTPを使用してディレクトリをダウンロードする も参照してください。


説明のために、コードが機能しない理由:

SftpClient.DownloadFileの2番目のパラメーターは、ダウンロードしたコンテンツを書き込むストリームです。

書き込みストリームの代わりに読み取りストリームを渡します。さらに、読み取りストリームを開くパスはリモートパスであり、ローカルファイルでのみ動作するFileクラスでは機能しません。

File.OpenRead行を破棄し、代わりに以前のFile.OpenWrite呼び出しの結果を使用します(今はまったく使用していません):

Stream file1 = File.OpenWrite(localFileName);

sftp.DownloadFile(file.FullName, file1);

または、さらに良いのは、File.Createを使用して、ローカルファイルにある以前のコンテンツを破棄することです。

あなたのlocalFileNameがフルパスを保持するのか、単にファイル名を保持するのかわからない。そのため、必要に応じてパスも追加する必要があります(localFileNamesDir?と組み合わせます)

35
Martin Prikryl

例は機能しますが、ストリームを処理する正しい方法ではありません...

sing句を使用してファイル/ストリームを確実に閉じる必要があります。また、try = catchを追加してIO errors ...

       public void DownloadAll()
    {
        string Host = @"sftp.domain.com";
        string username = "myusername";
        string password = "mypassword";

        string remoteDirectory = "/RemotePath/";
        string localDirectory = @"C:\LocalDriveFolder\Downloaded\";

        using (var sftp = new SftpClient(Host, username, password))
        {
            sftp.Connect();
            var files = sftp.ListDirectory(remoteDirectory);

            foreach (var file in files)
            {
                string remoteFileName = file.Name;
                if ((!file.Name.StartsWith(".")) && ((file.LastWriteTime.Date == DateTime.Today))

                    using (Stream file1 = File.OpenWrite(localDirectory + remoteFileName))
                    { 
                        sftp.DownloadFile(remoteDirectory + remoteFileName, file1);
                    }
            }

        }
    }
15
Merak Marey

@Merak Marey's Codeの私のバージョン。ファイルが既に存在しているかどうか、および.txtと他のファイルのダウンロードディレクトリが異なるかどうかを確認しています

        static void DownloadAll()
    {
        string Host = "xxx.xxx.xxx.xxx";
        string username = "@@@";
        string password = "123";string remoteDirectory = "/IN/";
        string finalDir = "";
        string localDirectory = @"C:\filesDN\";
        string localDirectoryZip = @"C:\filesDN\Zip\";
        using (var sftp = new SftpClient(Host, username, password))
        {
            Console.WriteLine("Connecting to " + Host + " as " + username);
            sftp.Connect();
            Console.WriteLine("Connected!");
            var files = sftp.ListDirectory(remoteDirectory);

            foreach (var file in files)
            {

                string remoteFileName = file.Name;

                if ((!file.Name.StartsWith(".")) && ((file.LastWriteTime.Date == DateTime.Today)))
                { 

                    if (!file.Name.Contains(".TXT"))
                    {
                        finalDir = localDirectoryZip;
                    } 
                    else 
                    {
                        finalDir = localDirectory;
                    }


                    if (File.Exists(finalDir  + file.Name))
                    {
                        Console.WriteLine("File " + file.Name + " Exists");
                    }else{
                        Console.WriteLine("Downloading file: " + file.Name);
                          using (Stream file1 = File.OpenWrite(finalDir + remoteFileName))
                    {
                        sftp.DownloadFile(remoteDirectory + remoteFileName, file1);
                    }
                    }
                }
            }



            Console.ReadLine();

        }
4
Tasos Mansour

特定のエラーメッセージを提供しなければ、具体的な提案をするのは困難です。

ただし、同じ例を使用して、File.OpenWriteでアクセス許可の例外を取得していました-localFileName変数を使用して、Path.GetFileを使用すると、明らかにファイルを開くためのアクセス許可がない場所を指しているため> C:\ ProgramFiles\IIS(Express)\ filename.doc

System.IO.Path.GetFileNameの使用が正しくないことがわかりました。代わりにSystem.IO.Path.GetFullPathを使用し、「C:\ ...」で始まるファイルをポイントしてください。

また、FileExplorerでソリューションを開き、ファイルまたはファイルを保持しているフォルダーのアクセス許可をasp.netに付与します。その時点でファイルをダウンロードできました。

0
Doug