Автоматически возобновлять загрузку SFTP после восстановления сетевого подключения с помощью SSH.NET

Я использую библиотеку SSH.NET для создания клиента SFTP. Мне нужно возобновить загрузку, если сетевое соединение снова станет доступным в течение этого тайм-аута. Я использую упомянутый ниже подход, как показано во многих примерах.

PrivateKeyFile ObjPrivateKey = new PrivateKeyFile(keyStream);
PrivateKeyAuthenticationMethod ObjPrivateKeyAutentication = new PrivateKeyAuthenticationMethod(username, ObjPrivateKey);

var connectionInfo = new ConnectionInfo(hostAddress, port, username, ObjPrivateKeyAutentication);

try
{
    using (var client = new SftpClient(connectionInfo))
    {
        client.ConnectionInfo.Timeout = TimeSpan.FromSeconds(10);

        client.Connect();

        if (!client.IsConnected)
        {
            return false;
        }

        if (!client.Exists(source))
        {
            return false;
        }

        var fileName = Path.GetFileName(source);

        using (var fs = new FileStream(destination + fileName, FileMode.Create))
        {
            client.DownloadFile(source, fs, printActionDel);
            fs.Close();
            returnState = true;
        }

        client.Disconnect();
        client.Dispose();
    }
}

Я отключаю сетевой кабель, чтобы прервать загрузку и проверить сценарий тайм-аута. Хотя я снова включаю подключение к Интернету в течение тайм-аута для возобновления загрузки, оно не возобновляется. Что я здесь делаю не так? Пожалуйста посоветуй.


person Rishanthakumar    schedule 23.05.2017    source источник


Ответы (1)


Если вы ожидаете, что SSH.NET повторно подключится в течение SftpClient.DownloadFile, этого не произойдет.

Вы должны самостоятельно выполнить повторное подключение и перенос резюме.

PrivateKeyFile ObjPrivateKey = new PrivateKeyFile(keyStream);
PrivateKeyAuthenticationMethod ObjPrivateKeyAutentication =
    new PrivateKeyAuthenticationMethod(username, ObjPrivateKey);

var connectionInfo =
    new ConnectionInfo(hostAddress, port, username, ObjPrivateKeyAutentication);

bool retry = false;

do
{
    bool retrying = retry;
    retry = false;

    using (var client = new SftpClient(connectionInfo))
    {
        client.Connect();

        if (!client.Exists(source))
        {
            return false;
        }

        var fileName = Path.GetFileName(source);
        var destinationFile = Path.Combine(destination, fileName);

        try
        {
            Stream destinationStream;
            if (retrying)
            {
                destinationStream = new FileStream(destinationFile, FileMode.Append);
            }
            else
            {
                destinationStream = new FileStream(destinationFile, FileMode.Create);
            }

            using (destinationStream)
            using (var sourceStream = client.Open(source, FileMode.Open))
            {
                sourceStream.Seek(destinationStream.Length, SeekOrigin.Begin);
                // You can simply use sourceStream.CopyTo(destinationStream) here.
                // But if you need to monitor download progress,
                // you have to loop yourself.
                byte[] buffer = new byte[81920];
                int read;
                ulong total = (ulong)destinationStream.Length;
                while ((read = sourceStream.Read(buffer, 0, buffer.Length)) != 0)
                {
                    destinationStream.Write(buffer, 0, read);
                    total = total + (ulong)read;
                    // report progress
                    printActionDel(total);
                }
            }
        }
        catch (SshException e)
        {
            retry = true;
        }
    }
}
while (retry);

Или используйте другую библиотеку SFTP, которая изначально поддерживает резюме.

Например, сборка WinSCP .NET автоматически возобновляется в своем _ 3_ метод.

SessionOptions sessionOptions = new SessionOptions
{
    Protocol = Protocol.Sftp,
    HostName = hostAddress,
    PortNumber = port,
    UserName = username,
    SshHostKeyFingerprint = "ssh-rsa 2048 xxxxxxxxxxx...=",
    SshPrivateKeyPath = keyPath
};

using (Session session = new Session())
{
    session.FileTransferProgress += session_FileTransferProgress;

    session.Open(sessionOptions);

    var fileName = Path.GetFileName(source);
    var destinationFile = Path.Combine(destination, fileName);

    session.GetFiles(source, destinationFile).Check();
}

GUI WinSCP может сгенерировать для вас шаблон кода загрузки SFTP, подобный приведенному выше.

(я автор WinSCP)

person Martin Prikryl    schedule 24.05.2017