使用SSH.NET恢复网络连接后自动恢复SFTP下载

bnl4lu3b  于 2023-02-01  发布在  .NET
关注(0)|答案(1)|浏览(118)

我正在使用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();
    }
}

我正在拔下网线中断下载并测试超时情况。虽然我在超时内再次启用互联网连接以恢复下载,但它没有恢复。我在这里做错了什么?请提供建议。

up9lanfz

up9lanfz1#

如果您期望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
        {
            var mode = retrying ? FileMode.Append : FileMode.Create;
            using (var destinationStream = new FileStream(destinationFile, mode))
            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 assembly确实会在其Session.GetFiles method中自动恢复。

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

WinSCP GUI可以为您生成一个类似上面的SFTP下载代码模板。

  • (我是WinSCP的作者)*

还有另一种选择,它使用一个专用的"重试"库,如Polly:
Retry SFTP if it fails?

相关问题