Как прервать действие из функции DownloadFile() класса SftpClient (SSH.NET)?

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

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

Я не смог найти никакого задокументированного способа прервать функцию обратного вызова Action для метода DownloadFile, поэтому я прибегнул к исключению.

Но проблема с таким подходом в том, что мое пользовательское исключение не перехватывается.

Есть идеи, как это исправить?


person c00000fd    schedule 09.04.2018    source источник


Ответы (2)


Вы можете использовать их асинхронный (хотя не настоящий асинхронный) поток, то есть BeginDownloadFile. Реализация IAsyncResult, возвращенная этим методом, SftpDownloadAsyncResult, предоставляет отмену через свойство IsDownloadCanceled.

person ejohnson    schedule 09.04.2018
comment
Спасибо за это. Я смог создать метод, чтобы сообщать о прогрессе и обрабатывать отмены для загрузок и загрузок Renci SSH, используя ваш совет здесь. - person WATYF; 31.01.2021

Помимо использования асинхронного интерфейса, предложенного @ejohnson, вы также можете просто закрыть поток вывода:

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);
    }
}
person Martin Prikryl    schedule 09.04.2018
comment
Да спасибо. Вот что я в итоге сделал. Хотя нет никакого способа отличить его от действия, прерванного пользователем. - person c00000fd; 09.04.2018
comment
Просто установите флаг (переменная bool) в обратном вызове и проверьте флаг в блоке catch. Или на самом деле, перепроверьте файл didUserAbortDownload. Смотрите мой обновленный ответ. - person Martin Prikryl; 09.04.2018