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,我之前使用过一些代码,并认为我可以改变这个过程,但这并不起作用。我使用的代码基于此example。
答案 0 :(得分:31)
使用SSH.NET库下载文件的简单工作代码是:
using (Stream fileStream = File.Create(@"C:\target\local\path\file.zip"))
{
sftp.DownloadFile("/source/remote/path/file.zip", fileStream);
}
另见Downloading a directory using SSH.NET SFTP in C#。
要解释为什么您的代码不起作用:
SftpClient.DownloadFile
的第二个参数是将下载内容写入的流。
您正在传入读取流而不是写入流。此外,您打开读取流的路径是一个远程路径,对于仅在本地文件上运行的File
类不起作用。
只需丢弃File.OpenRead
行并使用之前File.OpenWrite
调用的结果(您现在根本不使用):
Stream file1 = File.OpenWrite(localFileName);
sftp.DownloadFile(file.FullName, file1);
或者甚至更好,使用File.Create
丢弃本地文件可能具有的任何先前内容。
我不确定你的localFileName
是否应该保留完整路径,或者只是文件名。因此,如果需要,您可能还需要添加路径(将localFileName
与sDir
结合使用?)
答案 1 :(得分:15)
虽然该示例有效,但它不是处理流的正确方法......
您需要确保使用使用子句关闭文件/流。 另外,添加try / catch来处理IO错误......
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);
}
}
}
}
答案 2 :(得分:4)
我的@Merak Marey代码版本。我正在检查文件是否已经存在以及.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();
}
答案 3 :(得分:0)
如果没有您提供任何特定的错误消息,很难给出具体的建议。
但是,我使用相同的示例并且在File.OpenWrite上获取权限异常 - 使用localFileName变量,因为使用Path.GetFile指向显然没有打开文件权限的位置> C:\ PROGRAMFILES \ IIS(快递)\ filename.doc
我发现使用System.IO.Path.GetFileName不正确,请改用System.IO.Path.GetFullPath,指向以“C:\ ...”开头的文件。
还要在FileExplorer中打开您的解决方案,并为该文件或包含该文件的任何文件夹授予asp.net权限。那时我能够下载我的文件。
答案 4 :(得分:-1)
这可以解决我的问题。
var files = sftp.ListDirectory(remoteVendorDirectory).Where(f => !f.IsDirectory);
foreach (var file in files)
{
var filename = $"{LocalDirectory}/{file.Name}";
if (!File.Exists(filename))
{
Console.WriteLine("Downloading " + file.FullName);
var localFile = File.OpenWrite(filename);
sftp.DownloadFile(file.FullName, localFile);
}
}