使用 SSH.NET 上传到 SFTP 服务器失败并出现 SftpPathNotFoundException:'The system cannot find the path specified.'
Upload to SFTP server with SSH.NET fails with SftpPathNotFoundException: 'The system cannot find the path specified.'
我正在尝试使用 Renci 通过 SFTP 上传文件 SSH.NET。
正在连接:
连接到 sFTP 站点,使用 SSH.NET,似乎有效:SftpClient
的 IsConnected
returns 正确。
使用 FileZilla 连接 ,但是会触发此警告:
Server's Host Key is Unknown
正在上传:
1) 使用SftpClient
的UploadFile
方法:
client.UploadFile(fileStream, "/Path/" + fileName, null);
...我得到一个 Renci.SshNet.Common.SftpPathNotFoundException
:'The system cannot find the path specified.'
- 我试过对路径进行硬编码 - 结果相同。
- 我试过使用
SftpClient
的 WorkingDirectory
- 但它转换成一串看起来像中文的字符,也不起作用。
2) 使用SftpClient
的BeginUploadFile
方法:
client.BeginUploadFile(fileStream, "/Path/" + fileName, asyncCallback, null, UpdateUploadProgress);
...我没有得到 errors/exceptions,但是:
文件未上传
aSyncCallback
和 uploadCallback
似乎不起作用
3) 使用 FileZilla,我可以很好地上传(使用与上面完全相同的目标路径:“/Path/Filename.txt”)
我的代码:
var connectionInfo = new ConnectionInfo(IpAddress,
Port,
UserName,
new PasswordAuthenticationMethod(UserName, Password),
new PrivateKeyAuthenticationMethod("rsa.key"));
connectionInfo.Encoding = Encoding.Unicode;
using (var client = new SftpClient(connectionInfo))
{
client.Connect();
if (client.IsConnected)
{
Console.WriteLine("SSH-client is connected");
}
var fileStream = new FileStream(FileMaker.GetFullyQualifiedPath(), FileMode.Open);
client.BufferSize = 4 * 1024;
string fileName = new FileMaker().GetFileName();
//client.UploadFile(fileStream, "/Path/" + fileName, null);
AsyncCallback asyncCallback = new AsyncCallback(NotifyUploadComplete);
client.BeginUploadFile(fileStream, "/Path/" + fileName, asyncCallback, null, UpdateUploadProgress);
client.Disconnect();
}
回调处理程序:
private void UpdateUploadProgress(ulong uploaded)
{
MainViewModel mainViewModel = (MainViewModel)System.Windows.Application.Current.FindResource("mainViewModel");
mainViewModel.UploadProgress = uploaded;
}
private void NotifyUploadComplete(IAsyncResult result)
{
MessageBox.Show("File uploaded.", "File uploaded");
}
更新:
我做了一个最小的例子并测试了它(相同的结果)。
使用上传文件:
var connectionInfo = new ConnectionInfo(IpAddress,
Port,
UserName,
new PasswordAuthenticationMethod(UserName, Password),
new PrivateKeyAuthenticationMethod("rsa.key"));
connectionInfo.Encoding = Encoding.Unicode;
using (var client = new SftpClient(connectionInfo))
{
client.Connect();
if (client.IsConnected)
{
Console.WriteLine("SSH-client is connected");
}
var fileStream = new FileStream(@"C:\File.txt", FileMode.Open);
client.BufferSize = 4 * 1024;
client.UploadFile(fileStream, "/SSHUsersPath/File.txt", null);
//AsyncCallback asyncCallback = new AsyncCallback(NotifyUploadComplete);
//client.BeginUploadFile(fileStream, "/SSHUsersPath/File.txt", asyncCallback, null, UpdateUploadProgress);
client.Disconnect();
}
这里是请求的 FileZilla 日志文件的摘录:
2017-09-21 10:08:36 11252 1 Status: Connected to
sshserv.CENSORED.com 2017-09-21 10:08:36 11252 1 Status:
Retrieving directory listing... 2017-09-21 10:08:36 11252 1 Command:
pwd 2017-09-21 10:08:36 11252 1 Response: Current directory is:
"/SSHUsersPath" 2017-09-21 10:08:36 11252 1 Command: ls 2017-09-21
10:08:37 11252 1 Status: Listing directory /SSHUsersPath 2017-09-21
10:08:37 11252 1 Status: Directory listing of "/SSHUsersPath"
successful 2017-09-21 10:08:58 11252 3 Status: Connecting to
sshserv.CENSORED.com... 2017-09-21 10:08:58 11252 3 Response:
fzSftp started, protocol_version=8 2017-09-21 10:08:58 11252 3
Command: open "CENSORED@sshserv.CENSORED.com" 22 2017-09-21
10:08:59 11252 3 Command: Trust new Hostkey: Once 2017-09-21 10:09:00
11252 3 Command: Pass: ***** 2017-09-21 10:09:00 11252 3 Status:
Connected to sshserv.CENSORED.com 2017-09-21 10:09:00 11252 3
Status: Starting upload of C:\File.txt 2017-09-21 10:09:00 11252 3
Command: cd "/SSHUsersPath" 2017-09-21 10:09:01 11252 3 Response: New
directory is: "/SSHUsersPath" 2017-09-21 10:09:01 11252 3 Command: put
"C:\File.txt" "File.txt" 2017-09-21 10:09:01 11252 3 Command:
local:C:\File.txt => remote:/SSHUsersPath/File.txt 2017-09-21 10:09:01
11252 3 Status: File transfer successful, transferred 4 bytes in 1
second 2017-09-21 10:09:01 11252 3 Status: Retrieving directory
listing of "/SSHUsersPath"... 2017-09-21 10:09:01 11252 3 Command: ls
2017-09-21 10:09:01 11252 3 Status: Listing directory /SSHUsersPath
2017-09-21 10:09:02 11252 3 Status: Directory listing of
"/SSHUsersPath" successful 2017-09-21 10:09:17 11252 1 Status:
Deleting "/SSHUsersPath/File.txt" 2017-09-21 10:09:17 11252 1 Command:
rm "/SSHUsersPath/File.txt" 2017-09-21 10:09:18 11252 1 Response: rm
/SSHUsersPath/File.txt: OK
主要问题是:
connectionInfo.Encoding = Encoding.Unicode;
Encoding.Unicode
是 UTF-16。没有 SFTP 服务器会处理 UTF-16 编码的文件名。 SFTP 服务器应使用 UTF-8。因此 SSH.NET 默认为 Encoding.UTF8
。如果使用 UTF-8 服务器损坏了文件名中的非 ASCII 字符(.Encoding
是关于文件名,而不是文件内容),那一定是因为 SFTP 损坏并使用了一些旧编码。但可以肯定的是,它不是 UTF-16。它更像是一些 ISO*
编码或 Windows-*
编码。
另一个问题是,当您使用 BeginUploadFile
时,您不会等待它完成并立即断开连接。
我正在尝试使用 Renci 通过 SFTP 上传文件 SSH.NET。
正在连接:
连接到 sFTP 站点,使用 SSH.NET,似乎有效:
SftpClient
的IsConnected
returns 正确。使用 FileZilla 连接 ,但是会触发此警告:
Server's Host Key is Unknown
正在上传:
1) 使用SftpClient
的UploadFile
方法:
client.UploadFile(fileStream, "/Path/" + fileName, null);
...我得到一个 Renci.SshNet.Common.SftpPathNotFoundException
:'The system cannot find the path specified.'
- 我试过对路径进行硬编码 - 结果相同。
- 我试过使用
SftpClient
的WorkingDirectory
- 但它转换成一串看起来像中文的字符,也不起作用。
2) 使用SftpClient
的BeginUploadFile
方法:
client.BeginUploadFile(fileStream, "/Path/" + fileName, asyncCallback, null, UpdateUploadProgress);
...我没有得到 errors/exceptions,但是:
文件未上传
aSyncCallback
和uploadCallback
似乎不起作用
3) 使用 FileZilla,我可以很好地上传(使用与上面完全相同的目标路径:“/Path/Filename.txt”)
我的代码:
var connectionInfo = new ConnectionInfo(IpAddress,
Port,
UserName,
new PasswordAuthenticationMethod(UserName, Password),
new PrivateKeyAuthenticationMethod("rsa.key"));
connectionInfo.Encoding = Encoding.Unicode;
using (var client = new SftpClient(connectionInfo))
{
client.Connect();
if (client.IsConnected)
{
Console.WriteLine("SSH-client is connected");
}
var fileStream = new FileStream(FileMaker.GetFullyQualifiedPath(), FileMode.Open);
client.BufferSize = 4 * 1024;
string fileName = new FileMaker().GetFileName();
//client.UploadFile(fileStream, "/Path/" + fileName, null);
AsyncCallback asyncCallback = new AsyncCallback(NotifyUploadComplete);
client.BeginUploadFile(fileStream, "/Path/" + fileName, asyncCallback, null, UpdateUploadProgress);
client.Disconnect();
}
回调处理程序:
private void UpdateUploadProgress(ulong uploaded)
{
MainViewModel mainViewModel = (MainViewModel)System.Windows.Application.Current.FindResource("mainViewModel");
mainViewModel.UploadProgress = uploaded;
}
private void NotifyUploadComplete(IAsyncResult result)
{
MessageBox.Show("File uploaded.", "File uploaded");
}
更新: 我做了一个最小的例子并测试了它(相同的结果)。
使用上传文件:
var connectionInfo = new ConnectionInfo(IpAddress,
Port,
UserName,
new PasswordAuthenticationMethod(UserName, Password),
new PrivateKeyAuthenticationMethod("rsa.key"));
connectionInfo.Encoding = Encoding.Unicode;
using (var client = new SftpClient(connectionInfo))
{
client.Connect();
if (client.IsConnected)
{
Console.WriteLine("SSH-client is connected");
}
var fileStream = new FileStream(@"C:\File.txt", FileMode.Open);
client.BufferSize = 4 * 1024;
client.UploadFile(fileStream, "/SSHUsersPath/File.txt", null);
//AsyncCallback asyncCallback = new AsyncCallback(NotifyUploadComplete);
//client.BeginUploadFile(fileStream, "/SSHUsersPath/File.txt", asyncCallback, null, UpdateUploadProgress);
client.Disconnect();
}
这里是请求的 FileZilla 日志文件的摘录:
2017-09-21 10:08:36 11252 1 Status: Connected to sshserv.CENSORED.com 2017-09-21 10:08:36 11252 1 Status: Retrieving directory listing... 2017-09-21 10:08:36 11252 1 Command: pwd 2017-09-21 10:08:36 11252 1 Response: Current directory is: "/SSHUsersPath" 2017-09-21 10:08:36 11252 1 Command: ls 2017-09-21 10:08:37 11252 1 Status: Listing directory /SSHUsersPath 2017-09-21 10:08:37 11252 1 Status: Directory listing of "/SSHUsersPath" successful 2017-09-21 10:08:58 11252 3 Status: Connecting to sshserv.CENSORED.com... 2017-09-21 10:08:58 11252 3 Response: fzSftp started, protocol_version=8 2017-09-21 10:08:58 11252 3 Command: open "CENSORED@sshserv.CENSORED.com" 22 2017-09-21 10:08:59 11252 3 Command: Trust new Hostkey: Once 2017-09-21 10:09:00 11252 3 Command: Pass: ***** 2017-09-21 10:09:00 11252 3 Status: Connected to sshserv.CENSORED.com 2017-09-21 10:09:00 11252 3 Status: Starting upload of C:\File.txt 2017-09-21 10:09:00 11252 3 Command: cd "/SSHUsersPath" 2017-09-21 10:09:01 11252 3 Response: New directory is: "/SSHUsersPath" 2017-09-21 10:09:01 11252 3 Command: put "C:\File.txt" "File.txt" 2017-09-21 10:09:01 11252 3 Command: local:C:\File.txt => remote:/SSHUsersPath/File.txt 2017-09-21 10:09:01 11252 3 Status: File transfer successful, transferred 4 bytes in 1 second 2017-09-21 10:09:01 11252 3 Status: Retrieving directory listing of "/SSHUsersPath"... 2017-09-21 10:09:01 11252 3 Command: ls 2017-09-21 10:09:01 11252 3 Status: Listing directory /SSHUsersPath 2017-09-21 10:09:02 11252 3 Status: Directory listing of "/SSHUsersPath" successful 2017-09-21 10:09:17 11252 1 Status: Deleting "/SSHUsersPath/File.txt" 2017-09-21 10:09:17 11252 1 Command: rm "/SSHUsersPath/File.txt" 2017-09-21 10:09:18 11252 1 Response: rm /SSHUsersPath/File.txt: OK
主要问题是:
connectionInfo.Encoding = Encoding.Unicode;
Encoding.Unicode
是 UTF-16。没有 SFTP 服务器会处理 UTF-16 编码的文件名。 SFTP 服务器应使用 UTF-8。因此 SSH.NET 默认为 Encoding.UTF8
。如果使用 UTF-8 服务器损坏了文件名中的非 ASCII 字符(.Encoding
是关于文件名,而不是文件内容),那一定是因为 SFTP 损坏并使用了一些旧编码。但可以肯定的是,它不是 UTF-16。它更像是一些 ISO*
编码或 Windows-*
编码。
另一个问题是,当您使用 BeginUploadFile
时,您不会等待它完成并立即断开连接。