'No such file' exception when calling DownloadFile (SftpClient) asyncronously

Mar 28, 2013 at 2:32 AM
I am trying to download bunch of files from SFTP directory (and enclosed sub-directories) bases on certain criteria. First I list directory content and then iterate the result list downloading files and processing sub-directories recursively. It looks fine doing synchronously (several hundred files were downloaded successfully).
When I call BeginDownloadFile() from the loop in the main thread of application and use AsyncCallback to complete the operation (which calls EndDownloadFile(), as well as flushing/closing FileStream), I receive 'No such file' exception every time except for very first downloaded file (i am not even sure if it was 'successful' - it has some data in - not 0-length file, like every next one, but I am not sure if it is complete).
In both cases I use 'absolute' file names (which I retrieve first from ListDirectory() call), the only difference is using async method with supplied callback. I can provide code snippet for this.
When I call BeginDownloadFile() in a loop, I use the same SftpClient object I created and connected before - could it be a problem to use the same client object for multiple async requests?
Coordinator
Apr 6, 2013 at 6:00 PM
Hi,

Can you post a code example of what you doing so I could try to recreate it here?

Thanks,
Oleg
Apr 8, 2013 at 11:22 PM
Edited Apr 9, 2013 at 3:05 PM
here is a code sample i use:
class Processor : IDisposable
{
        private class StateData
        {
            public Processor Processor { get; set; }
            public FileStream FileStream { get; set; }
            public string FileName { get; set; }
        }

private SftpClient m_sftpClient;
private string m_strTestBase = @"/Home/aaa/bbb";
private AsyncCallback m_asyncCallback = new AsyncCallback(CompleteDownload);

internal void Process()
{
....
m_sftpClient = new SftpClient("xxx", "yyy", "zzz");
m_sftpClient.Connect();
ProcessDirectory(m_strTestBase);
....
}

private static void CompleteDownload(IAsyncResult result)
        {
            SftpDownloadAsyncResult sftpDownloadAsyncResult = (SftpDownloadAsyncResult)result;

            StateData stateData = (StateData)result.AsyncState;
            Processor proc = stateData.Processor;

            try
            {
                proc.m_sftpClient.EndDownloadFile(result);
                Interlocked.Increment(ref proc.m_iDownloadedCnt);

                // Write Console Output
                Console.WriteLine("Success: " + stateData.FileName);
            }
            catch(Exception ex)
            {
                Interlocked.Increment(ref proc.m_iFailedCnt);
                Console.WriteLine("Exception in 'CompleteDownload' [" + stateData.FileName  + "]: " + ex.Message);
            }
            finally
            {
                try
                {
                    stateData.FileStream.Flush();
                    stateData.FileStream.Dispose();
                }
                catch
                {
                }

                if (Interlocked.Decrement(ref s_iRequestCounter) == 0)
                {
                    proc.m_iEndProcessingEvent.Set();
                }

            }
        }

        private void ProcessFile(string strFile)
        {
            string str1 = strFile.Substring(m_strTestBase.Length + 1).Replace('/', '\\');
            string strOutFileNameLong = Path.Combine(m_strTestOutputDataDir, str1);
            if (!File.Exists(strOutFileNameLong))
            {
                string strOutDir = Path.GetDirectoryName(strOutFileNameLong);
                if (!Directory.Exists(strOutDir))
                {
                    Directory.CreateDirectory(strOutDir);
                }

                FileStream fs = File.Create(strOutFileNameLong, 4096, FileOptions.Asynchronous);
                StateData stateData = new StateData { Processor = this, FileName = strOutFileNameLong, FileStream = fs };

                Console.WriteLine("S: " + strFile + "   ---   D: " + strOutFileNameLong);


                Interlocked.Increment(ref s_iRequestCounter);
                m_sftpClient.BeginDownloadFile(strFile, fs, m_asyncCallback, stateData);
            }
            else
            {
                m_iSkippedCnt++;
            }

        }

        private void ProcessDirectory(string strDirectory)
        {
            var vFiles = m_sftpClient.ListDirectory(strDirectory);
            foreach (var vFile in vFiles)
            {
                if (vFile.IsDirectory)
                {
                    ProcessDirectory(vFile.FullName);
                }
                else if (vFile.IsRegularFile)
                {
                    ProcessFile(vFile.FullName);
                }
            }
        }