Загрузка на SFTP-сервер с SSH.NET завершается с ошибкой SftpPathNotFoundException: "Системе не удается найти указанный путь".
Я пытаюсь загрузить файл через SFTP, используя Renci SSH.NET.
Подключение:
Подключение к sFTP-сайту, используя SSH.NET, похоже работает:
SftpClient
"sIsConnected
возвращает истину.Однако при подключении с использованием FileZilla выдается следующее предупреждение:
Ключ хоста сервера неизвестен
Загрузка:
1) Использование SftpClient
"s UploadFile
метод:
client.UploadFile(fileStream, "/Path/" + fileName, null);
... я получаю Renci.SshNet.Common.SftpPathNotFoundException
: 'Система не может найти указанный путь.'
- Я пробовал жестко закодировать путь - тот же результат.
- Я пытался использовать
SftpClient
"sWorkingDirectory
- но это переводится в строку китайских символов и тоже не работает.
2) Использование SftpClient
"s BeginUploadFile
метод:
client.BeginUploadFile(fileStream, "/Path/" + fileName, asyncCallback, null, UpdateUploadProgress);
... я не получаю ошибок / исключений, но:
файл не загружен
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");
}
ОБНОВЛЕНИЕ: я сделал минимальный пример и проверил его (тот же результат).
Использование UploadFile:
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 Статус: подключен к sshserv.CENSORED.com 2017-09-21 10:08:36 11252 1 Статус: получение списка каталогов... 2017-09-21 10:08:36 11252 1 команда: pwd 2017-09-21 10:08:36 11252 1 Ответ: текущий каталог: "/SSHUsersPath" 2017-09-21 10:08:36 11252 1 команда: ls 2017-09-21 10:08:37 11252 1 Статус: каталог листинга /SSHUsersPath 2017-09-21 10:08:37 11252 1 Статус: список каталогов "/ SSHUsersPath" успешен 2017-09-21 10:08:58 11252 3 Статус: подключение к sshserv.CENSORED.com... 2017-09-21 10:08:58 11252 3 Ответ: fzSftp запущен, protocol_version=8 2017-09-21 10:08:58 11252 3 Команда: открыть "CENSORED@sshserv.CENSORED.com" 22 2017-09-21 10:08:59 11252 3 Команда: Доверять новому ключу хоста: Один раз 2017-09-21 10:09:00 11252 3 Команда: Пропустить: ***** 2017-09-21 10:09:00 11252 3 Статус: подключен к sshserv.CENSORED.com 2017-09-21 10:09:00 11252 3 Статус: начинается загрузка C:\File.txt 2017-09-21 10:09:00 11252 3 Команда: cd "/SSHUsersPath" 2017-09-21 10:09:01 11252 3 Ответ: Новый каталог: "/SSHUsersPath" 2017-09-21 10:09:01 11252 3 Команда: положить "C:\File.txt" "File.txt" 2017-09-21 10:09:01 11252 3 Команда: локальная:C:\File.txt => remote:/SSHUsersPath/File.txt 2017-09-21 10:09:01 11252 3 Статус: Передача файла прошла успешно, 4 байта переданы за 1 секунду 2017-09-21 10:09:01 11252 3 Статус: получение списка каталогов "/SSHUsersPath"... 2017-09-21 10:09:01 11252 3 Команда: ls 2017-09-21 10:09:01 11252 3 Статус: список directory /SSHUsersPath 2017-09-21 10:09:02 11252 3 Статус: список каталогов "/ SSHUsersPath" успешно 2017-09-21 10:09:17 11252 1 Статус: удаление "/SSHUsersPath/File.txt" 2017-09-21 10:09:17 11252 1 команда: rm "/SSHUsersPath/File.txt" 2017-09-21 10:09:18 11252 1 Ответ: rm /SSHUsersPath/File.txt: OK
1 ответ
Основная проблема заключается в следующем:
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
, вы не дожидаетесь его окончания и сразу же отключаете.