65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 C# 和 PSFTP 实现简易 SFTP(安全 FTP)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.60/5 (7投票s)

2014年2月3日

CPOL

1分钟阅读

viewsIcon

64825

使用 PLINK 作为进程在 C# 中进行 SFTP 文件传输

引言

市面上有很多 .NET 项目允许你使用 SFTP,但所有我尝试过的都令人困惑或者根本无法工作。PuTTY(一个开源的 telnet/SSH/等客户端)的开发者制作了一个命令行应用程序(PSFTP,在这里下载),专门为编写 SFTP 脚本的人们设计。本质上,它是一个命令行应用程序,它接受一些参数并可以运行一个批处理脚本。下面的代码是使用它与你的 C# 应用程序的基本介绍。它会自动生成批处理脚本并作为进程运行 PSFTP。有关 PSFTP 的更多用法,请阅读这里的文档

两个注意事项

  1. 在运行下面的脚本之前,你必须接受来自你要连接的服务器的 SSH 证书,否则它将无法工作。为此,只需使用 PuTTY 或其他 SSH 客户端连接到服务器并接受其证书即可;
  2. 这仅用于 SFTP!对于常规 FTP,请查看我这里的另一篇文章。

Using the Code

class Program
{
    static void Main(string[] args)
    {
        //Files on the server
        string[] remoteFiles = new string[]
        {
            @"/etc/remote-file1.txt",
            @"/etc/remote-file2.txt",
            @"/etc/remote-file3.txt"
        };
        //Files on your computer
        string[] localFiles = new string[]
        {
            @"C:\local-file1.txt",
            @"C:\local-file2.txt",
            @"C:\local-file3.txt"
        };
        //Other commands (not download/upload)
        string[] commands = new string[]
        {
            @"cd /home",
            @"dir"
        };

        //Create the object and run some commands!
        PSFTP PsftpClient = new PSFTP(@"10.10.10.10", @"root", @"password");
        PsftpClient.Get(remoteFiles, localFiles);
        PsftpClient.Put(remoteFiles, localFiles);
        PsftpClient.SendCommands(commands);

        Console.WriteLine(PsftpClient.Outputs);

        PsftpClient = null;
    }
}  

以下是实际代码。你需要确保你正在“使用System.Diagnostics

class PSFTP
{
    private string _Host;
    private string _User;
    private string _Password;

    private string _BatchFilePath = @"C:\batch.txt";
    private string _PsftpPath = @"C:\psftp"; /* Change this to the location 
    		of the PSTFP app.  Do not include the '.exe' file extension. */
    public string Outputs = ""; /* Stores the outputs and errors of PSFTP */

    /* Object Constructor for standard usage */
    public PSFTP(string Host, string User, string Password)
    {
        _Host = Host;
        _User = User;
        _Password = Password;
    }

    /* Object Constructor for Threading */
    /* Specify the commands carefully */
    public PSFTP(string Host, string User, string Password, string[] Commands)
    {
        _Host = Host;
        _User = User;
        _Password = Password;
        GenerateBatchFile(Commands);
    }

    /* Retrieve files from the server */
    public void Get(string[] Remote, string[] Local)
    {
        /* Format the commands */
        string[] Commands = new string[Remote.Count()];

        for (int i = 0; i < Remote.Count(); i++)
        {
            Commands[i] = @"get " + Remote[i] + @" " + Local[i];
        }

        GenerateBatchFile(Commands);

        Run();

        return;
    }

    /* Send files from your computer to the server */
    public void Put(string[] Remote, string[] Local)
    {
        /* Format the commands */
        string[] Commands = new string[Remote.Count()];

        for (int i = 0; i < Remote.Count(); i++)
        {
            Commands[i] = @"put " + Remote[i] + @" " + Local[i];
        }

        GenerateBatchFile(Commands);

        Run();

        return;
    }

    /* Use this to send other SFTP commands (CD, DIR, etc.) */
    public void SendCommands(string[] commands)
    {
        GenerateBatchFile(commands);

        Run();

        return;
    }

    /* Create a text file with a list of commands to be fed into PSFTP */
    private void GenerateBatchFile(string[] Commands)
    {
        try
        {
            StreamWriter batchWriter = new StreamWriter(_BatchFilePath);

            /* Write each command to the batch file */
            for (int i = 0; i < Commands.Count(); i++)
            {
                batchWriter.WriteLine(Commands[i]);
            }

            /* Command to close the connection */
            batchWriter.WriteLine(@"bye");

            batchWriter.Close();
        }
        catch (Exception ex) { Console.WriteLine(ex.ToString()); }

        return;
    }

    /* Run the commands, store the outputs */
    private void Run()
    {
        /* Execute PSFTP as a System.Diagnostics.Process using the supplied login info and generated batch file */
        try
        {
            ProcessStartInfo PsftpStartInfo = new ProcessStartInfo(_PsftpPath, 
            _User + @"@" + _Host + @" -pw " + _Password + @" -batch -be -b " + _BatchFilePath);

            /* Allows redirecting inputs/outputs of PSFTP to your app */
            PsftpStartInfo.RedirectStandardInput = true;
            PsftpStartInfo.RedirectStandardOutput = true;
            PsftpStartInfo.RedirectStandardError = true;
            PsftpStartInfo.UseShellExecute = false;

            Process PsftpProcess = new Process();
            PsftpProcess.StartInfo = PsftpStartInfo;
            PsftpProcess.Start();

            /* Streams for capturing outputs and errors as well as taking ownership of the input */
            StreamReader PsftpOutput = PsftpProcess.StandardOutput;
            StreamReader PsftpError = PsftpProcess.StandardError;
            StreamWriter PsftpInput = PsftpProcess.StandardInput;


            while (!PsftpOutput.EndOfStream)
            {
                try
                {
                    /* This is usefule for commands other than 'put' or 'get' 
and for catching errors. */ Outputs += PsftpOutput.ReadLine(); Outputs += PsftpError.ReadLine(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } } PsftpOutput.Close(); PsftpError.Close(); PsftpInput.Close(); PsftpProcess.WaitForExit(); PsftpStartInfo = null; PsftpProcess = null; } catch (Exception ex) { Console.WriteLine(ex.ToString()); } /* Delete the batch file */ try { File.Delete(_BatchFilePath); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } return; } }

关注点

根据你的需要,肯定还有空间添加更多功能。将此代码进行多线程处理并不困难。

 
© . All rights reserved.