Automatically resume SFTP download after network connection is restored with SSH.NET

↘锁芯ラ 提交于 2019-12-01 08:48:53

If you expect the SSH.NET to reconnect within SftpClient.DownloadFile, it won't.

You have to implement the re-connect and transfer resume on your own.

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);

Or use another SFTP library that supports the resume natively.

For example WinSCP .NET assembly does resume automatically in its Session.GetFiles method.

SessionOptions sessionOptions = new SessionOptions
{
    Protocol = Protocol.Sftp,
    HostName = hostAddress,
    PortNumber = port,
    UserName = username,
    SshHostKeyFingerprint = "ssh-dss 2048 0b:77:8b:68:f4:45:b1:3c:87:ad:5c:be:3b:c5:72:78",
    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();
}

WinSCP GUI can generate an SFTP download code template like the one above for you.

(I'm the author of WinSCP)

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!