3

I'm using SSH.NET to implement downloading of a file via secure SSH/SFTP connection. I need also to be able to see the progress of the download and to be able to abort it if a user wants it. So the code looks like this:

ConnectionInfo conn = new PasswordConnectionInfo(host, port, username, password);
SftpClient sshSFTP = new SftpClient(conn);
sshSFTP.Connect();

try
{
    FileStream streamFile = File.Create(strLocalFilePath);

    sshSFTP.DownloadFile(strFilePath, streamFile,
        (ulong uiProcessedSize) =>
        {
            //Callback
            processProgress(uiProcessedSize);

            if(didUserAbortDownload())
            {
                //Aborted
                throw new Exception("Aborted by the user");
            }
        });
}
catch (Exception ex)
{
    Console.WriteLine("Download failed: " + ex.Message);
}

streamFile.Close();
sshSFTP.Disconnect();

I couldn't find any documented way to abort the Action callback function for the DownloadFile method, so I resorted to throwing an exception.

But the problem with such approach is that my custom exception is not caught.

Any idea how to remedy this?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
c00000fd
  • 20,994
  • 29
  • 177
  • 400

2 Answers2

1

You can use their async (though not true async) flow, i.e. BeginDownloadFile. The IAsyncResult implementation returned by that method, SftpDownloadAsyncResult, exposes cancellation through its IsDownloadCanceled property.

ejohnson
  • 655
  • 7
  • 18
  • Thanks for this. I was able to put together a Method to report progress and handle cancellations for Renci SSH Uploads and Downloads using your tip here. – WATYF Jan 31 '21 at 19:40
1

Apart from using asynchronous interface, as suggested by @ejohnson, you can also just close the output stream:

try
{
    FileStream streamFile = File.Create(strLocalFilePath);

    sshSFTP.DownloadFile(strFilePath, streamFile,
        (ulong uiProcessedSize) =>
        {
            //Callback
            processProgress(uiProcessedSize);

            if(didUserAbortDownload())
            {
                //Aborted
                streamFile.Close();
            }
        });
}
catch (Exception ex)
{
    if(didUserAbortDownload())
    {
        Console.WriteLine("Download cancelled");
    }
    else
    {
        Console.WriteLine("Download failed: " + ex.Message);
    }
}
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992