0 votes
by (480 points)
edited by

I want to to avoid duplicate file listing while downloading files via rebex.

Actually I got a solution for memory exception to fetch large volume of files from rebex for a single file type. But while doing so for multiple Inward file types and extensions for each message type,We are looping the message type and Extensions as enumerators for each message type count is not coming fine with new Code.

public enum Extension
{
    SHA =1,
    DDR = 2,
    PDF = 3,
    ACK = 4,
    NAK = 5,
}  

public enum InwardMessageType
{
    DDS210 = 210,
    DDS300 = 300,
    DDS310 = 310,
    DDS400 = 400,
    DDS501 = 501,
    DDS503 = 503,
    DDS598 = 598,
    ACKNAK = 10,
    REP =12,       
}

Existing Method

    private List<SFTPFile> ListInwardCBFiles()
    {
        _listSftp = new Sftp();
        SFTPFile objSFTPFile;
        List<SFTPFile> ListSFTPFile = new List<SFTPFile>();
        try
        {
            if (ConnectSftp(_listSftp))
            {
                foreach (InwardMessageType t in Enum.GetValues(typeof(InwardMessageType)))
                {

                    foreach (CBExtension r in Enum.GetValues(typeof(CBExtension)))
                    {

                        SftpItemCollection List = _listSftp.GetList(GetSFTPServerPath(Enum.GetName(typeof(InwardMessageType), t)) + "//" + "*." + Enum.GetName(typeof(CBExtension), r));

                        foreach (SftpItem item in List)
                        {
                            objSFTPFile = new SFTPFile();
                            objSFTPFile.FileType = Enum.GetName(typeof(InwardMessageType), t);
                            objSFTPFile.Extension = Enum.GetName(typeof(CBExtension), r);
                            objSFTPFile.Status = SFTPStatus.L.ToString();
                            objSFTPFile.FileName = item.Name.Trim();
                            objSFTPFile.FileSize = item.Size;
                            objSFTPFile.Mode = SFTPMode.D.ToString();
                            objSFTPFile.BankCode = Common.BANKCODE;
                            ListSFTPFile.Add(objSFTPFile);
                            Common.WriteLog(MethodInfo.GetCurrentMethod().Name + " FileType: " + objSFTPFile.FileType + " FileName: " + objSFTPFile.FileName, ServiceThread.Listing.ToString());

                        }

                    }
                }
            }
        }
        catch (Exception ex)
        {
            Common.WriteLog("Exception while listing files in the folder " + Environment.NewLine + ex.Message, ServiceThread.Listing.ToString());

        }
        finally
        {
            DisConnectSftp(_listSftp);
        }

        return ListSFTPFile;
    }

Rebex Code

    private List<SFTPFile> ListInwardCBFilesRebexCode()
    {
        _listSftp = new Sftp();
        SFTPFile objSFTPFile;
        List<SFTPFile> ListSFTPFile = new List<SFTPFile>();
        try
        {
            if (ConnectSftp(_listSftp))
            {
                foreach (InwardMessageType t in Enum.GetValues(typeof(InwardMessageType)))
                {

                    foreach (CBExtension r in Enum.GetValues(typeof(CBExtension)))
                    {

                        _listSftp.ListItemReceived += (s, e) =>
                        {
                            SftpItem item = e.Item;
                            objSFTPFile = new SFTPFile();
                            objSFTPFile.FileType = Enum.GetName(typeof(InwardMessageType), t);
                            objSFTPFile.Extension = Enum.GetName(typeof(CBExtension), r);
                            objSFTPFile.Status = SFTPStatus.L.ToString();
                            objSFTPFile.FileName = item.Name.Trim();
                            objSFTPFile.FileSize = item.Size;
                            objSFTPFile.Mode = SFTPMode.D.ToString();
                            objSFTPFile.BankCode = Common.BANKCODE;
                            ListSFTPFile.Add(objSFTPFile);
                            Common.WriteLog(MethodInfo.GetCurrentMethod().Name + " FileType: " + objSFTPFile.FileType + " FileName: " + objSFTPFile.FileName, ServiceThread.Listing.ToString());
                            // skip adding item to resulting collection
                            e.Ignore();
                        };

                        // clear resulting collection first
                        //ListSFTPFile.Clear();

                        // issue directory listing

                        SftpItemCollection List = _listSftp.GetList(GetSFTPServerPath(Enum.GetName(typeof(InwardMessageType), t)) + "//" + "*." + Enum.GetName(typeof(CBExtension), r));
                        //SftpItemCollection List = _listSftp.GetList(GetSFTPServerPath("DDS300"));

            }
                }

            }
        }
        catch (Exception ex)
        {
            Common.WriteLog("Exception while listing files in the folder " + Environment.NewLine + ex.Message, ServiceThread.Listing.ToString());

        }
        finally
        {
            DisConnectSftp(_listSftp);
        }

        return ListSFTPFile;
    }
Applies to: Rebex SFTP

1 Answer

0 votes
by (70.2k points)
edited by

You are registering _listSftp.ListItemReceived += again and again in every loop cycle, which means that the code is executed multiple times.

Either register the event once or unregister the event after each use.

Since you are using local cycle variables in handler, easier would be the second case. It can be done like this:

private List<SFTPFile> ListInwardCBFilesRebexCode()
{
    _listSftp = new Sftp();
    SFTPFile objSFTPFile;
    List<SFTPFile> ListSFTPFile = new List<SFTPFile>();
    try
    {
        if (ConnectSftp(_listSftp))
        {
            foreach (InwardMessageType t in Enum.GetValues(typeof(InwardMessageType)))
            {

                foreach (CBExtension r in Enum.GetValues(typeof(CBExtension)))
                {
                    var listItemReceived = new SftpListItemReceivedEventHandler((s, e) =>
                    {
                        SftpItem item = e.Item;
                        objSFTPFile = new SFTPFile();
                        objSFTPFile.FileType = Enum.GetName(typeof(InwardMessageType), t);
                        objSFTPFile.Extension = Enum.GetName(typeof(CBExtension), r);
                        objSFTPFile.Status = SFTPStatus.L.ToString();
                        objSFTPFile.FileName = item.Name.Trim();
                        objSFTPFile.FileSize = item.Size;
                        objSFTPFile.Mode = SFTPMode.D.ToString();
                        objSFTPFile.BankCode = Common.BANKCODE;
                        ListSFTPFile.Add(objSFTPFile);
                        Common.WriteLog(MethodBase.GetCurrentMethod().Name + " FileType: " + objSFTPFile.FileType + " FileName: " + objSFTPFile.FileName, ServiceThread.Listing.ToString());

                        // skip adding item to resulting collection
                        e.Ignore();
                    });

                    // register the event handler
                    _listSftp.ListItemReceived += listItemReceived;
                    try
                    {
                        // issue directory listing
                        SftpItemCollection List = _listSftp.GetList(GetSFTPServerPath(Enum.GetName(typeof(InwardMessageType), t)) + "//" + "*." + Enum.GetName(typeof(CBExtension), r));
                        //SftpItemCollection List = _listSftp.GetList(GetSFTPServerPath("DDS300"));
                    }
                    finally
                    {
                        // unregister the event handler
                        _listSftp.ListItemReceived -= listItemReceived;
                    }
                }
            }

        }
    }
    catch (Exception ex)
    {
        Common.WriteLog("Exception while listing files in the folder " + Environment.NewLine + ex.Message, ServiceThread.Listing.ToString());

    }
    finally
    {
        DisConnectSftp(_listSftp);
    }

    return ListSFTPFile;
}
by (480 points)
Can u give a more clear code if possible to the same for us to understand precisely ?
by (144k points)
I added the whole ListInwardCBFilesRebexCode method to our response. You have to call "_listSftp.ListItemReceived -= listItemReceived" for each "_listSftp.ListItemReceived += listItemReceived".
by (144k points)
However, the need to unregister events is not imposed by Rebex SFTP - it's the nature of .NET events. Explaining how .NET's events work and fixing bugs in custom code is beyond the scope of Rebex support.
There are plenty of information about this on the Internet. For introduction to events in C# and their pitfalls, check out https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/events/how-to-subscribe-to-and-unsubscribe-from-events or https://stackoverflow.com/questions/183367/unsubscribe-anonymous-method-in-c-sharp
by (144k points)
But I have to point out that the ListInwardCBFilesRebexCode method doesn't seem quite right. It does the filtering twice (it both passes a mask to GetList method and also does a custom filtering), and you call it multiple times, which is inefficient if all the items are in the same directory.
by (480 points)
We  were able to download bulk files via sftp by registering and un registering the register method.
" listSftp.ListItemReceived += listItemReceived//Register

"_listSftp.ListItemReceived -= listItemReceived//Un register

 How can we do the same by registering  the event once and invoke instead of registering and un registering the rebex list object during each loop call
by (144k points)
Restructure your code so that the event handler is only registered once for each _listSftp and keep in mind it would be raised in all subsequent _list.GetList/GetRawList/GetNameList method calls.

However, this is a C# question that is outside the scope of Rebex support. If you need an advice on C# or an in-depth explanation of C# events, consider asking at a programming forum such as StackOverflow (https://stackoverflow.com/questions/tagged/c%23).
by (480 points)
As discussed, I have registered the event handler once without unregistering for each loop cycles . But I am unable to list files since it is unable to pass additional parameters(say Inward message types and their respective values) to the event handler SftpListItemReceivedEventHandler . Awaiting a response on this soon.

 I have updated the entire core code below:

Code:
   #region ListInwardCBFiles
        private List&lt;sftpfile&gt; ListInwardCBFiles()
      {
         _listSftp = new Sftp();
         SFTPFile objSFTPFile;
         List&lt;sftpfile&gt; ListSFTPFile = new List&lt;sftpfile&gt;();
         try
         {
             if (ConnectSftp(_listSftp))
             {
                 objSFTPFile = new SFTPFile();
                 foreach (InwardMessageType t in Enum.GetValues(typeof(InwardMessageType)))
                 {

                     foreach (CBExtension r in Enum.GetValues(typeof(CBExtension)))
                     {
                    
                         _listSftp.ListItemReceived += client_ListItemReceived;//register
                         _listSftp.GetList(GetSFTPServerPath(Enum.GetName(typeof(InwardMessageType), t)) + "//" + "*." + Enum.GetName(typeof(CBExtension), r));
                         
                     }
                 }

             }
         }
         catch (Exception ex)
         {
             Common.WriteLog("Exception while listing files in the folder " + Environment.NewLine + ex.Message, ServiceThread.Listing.ToString());

         }
         finally
         {
             DisConnectSftp(_listSftp);
         }

         return ListSFTPFile;
 }
 #endregion


 void client_ListItemReceived(object sender, SftpListItemReceivedEventArgs e)
        {
            
             var listItemReceived = new SftpListItemReceivedEventHandler((s, e1) =&gt;
                          {
                              SftpItem item = e1.Item;
                            
                              objSFTPFile.FileType = Enum.GetName(typeof(InwardMessageType), t);
                              objSFTPFile.Extension = Enum.GetName(typeof(CBExtension), r);
                              objSFTPFile.Status = SFTPStatus.L.ToString();
                              objSFTPFile.FileName = item.Name.Trim();
                              objSFTPFile.FileSize = item.Size;
                              objSFTPFile.Mode = SFTPMode.D.ToString();
                              objSFTPFile.BankCode = Common.BANKCODE;
                              ListSFTPFile.Add(objSFTPFile);
                              Common.WriteLog(MethodInfo.GetCurrentMethod().Name + " FileType: " + objSFTPFile.FileType + " FileName: " + objSFTPFile.FileName, ServiceThread.Listing.ToString());
                              e1.Ignore();
                          });
                    
                         _listSftp.ListItemReceived += client_ListItemReceived;//register
                         _listSftp.GetList(GetSFTPServerPath(Enum.GetName(typeof(InwardMessageType), t)) + "//" + "*." + Enum.GetName(typeof(CBExtension), r));
                         
                     }
                 }

             }
        }
...