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






4.60/5 (7投票s)
使用 PLINK 作为进程在 C# 中进行 SFTP 文件传输
引言
市面上有很多 .NET 项目允许你使用 SFTP,但所有我尝试过的都令人困惑或者根本无法工作。PuTTY(一个开源的 telnet/SSH/等客户端)的开发者制作了一个命令行应用程序(PSFTP,在这里下载),专门为编写 SFTP 脚本的人们设计。本质上,它是一个命令行应用程序,它接受一些参数并可以运行一个批处理脚本。下面的代码是使用它与你的 C# 应用程序的基本介绍。它会自动生成批处理脚本并作为进程运行 PSFTP。有关 PSFTP 的更多用法,请阅读这里的文档。
两个注意事项
- 在运行下面的脚本之前,你必须接受来自你要连接的服务器的 SSH 证书,否则它将无法工作。为此,只需使用 PuTTY 或其他 SSH 客户端连接到服务器并接受其证书即可;
- 这仅用于 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;
}
}
关注点
根据你的需要,肯定还有空间添加更多功能。将此代码进行多线程处理并不困难。