B4J Question ftp.list issue... No files returned

David Elkington

Active Member
Licensed User
Longtime User
Hi All

I am trying to download a load of files from an FTP server, I connect ok, and can read the folder names in the top level, but don't seem to be able to go down to get files at subdirectory levels, files(i) always comes back as Zero. I have tried changing paths, sending FTP commands but nothing works.

It always lists the files in the top level. Have attached Screenshot




Here is my code.... it is basically taken from the FTP example

B4X:
'Non-UI application (console / server application)
#Region Project Attributes
    #CommandLineArgs:
    #MergeLibraries: True
#End Region

Sub Process_Globals
    Dim ftp As FTP
 
End Sub

Sub AppStart (Args() As String)
 
    ftp.Initialize("FTP","100.118.18.180","21","user","1234")
    ftp.TimeoutMs=30000
    ftp.PassiveMode=True
    ftp.List("/SOLON7/MON/")
    StartMessageLoop
End Sub

'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
    Return True
End Sub

Sub FTP_ListCompleted (ServerPath As String, Success As Boolean, Folders() As FTPEntry, Files() As FTPEntry)
    Log(ServerPath)
    If Success = False Then
        Log(LastException)
    Else
        For i = 0 To Folders.Length - 1
            Log(Folders(i).Name)
        Next
        For i = 0 To Files.Length - 1
            Log(Files(i).Name & ", " & Files(i).Size & ", " & DateTime.Date(Files(i).Timestamp))
        Next
    End If
End Sub
 

Attachments

  • Screenshot 2019-01-21 at 12.09.16.png
    Screenshot 2019-01-21 at 12.09.16.png
    110.2 KB · Views: 294

Daestrum

Expert
Licensed User
Longtime User
I think (so that means I could be wrong) you just read the root directory, then list the files.

If the root has no files in it then it will be blank.

I ran your code and got similar result (although my root does have files in it so they were listed), until I read each folder with ftp, then I got the files in each sub folders returned to me.
 
Upvote 0

David Elkington

Active Member
Licensed User
Longtime User
I think (so that means I could be wrong) you just read the root directory, then list the files.

If the root has no files in it then it will be blank.

I ran your code and got similar result (although my root does have files in it so they were listed), until I read each folder with ftp, then I got the files in each sub folders returned to me.

When you say "read each folder with FTP", how did you do that? I copied some files into root and yes, it did read those, but never for the subfolders.
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
For each folder it found I appended the name to the root folder name then read that with ftp.
B4X:
Sub Process_Globals
 Dim ftp As FTP
  Dim ftp2 As FTP
 Dim root As String = "/GoFlex Home Public/"
End Sub
Sub AppStart (Args() As String)
 
 ftp.Initialize("FTP","192.168.0.11","21","xxxxx","xxxxxxx")
 ftp.TimeoutMs=30000
 ftp.PassiveMode=True
 ftp.List(root)
 StartMessageLoop
End Sub
'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
 Return True
End Sub
Sub FTP_ListCompleted (ServerPath As String, Success As Boolean, Folders() As FTPEntry, Files() As FTPEntry)
 Log(ServerPath)
 If Success = False Then
  Log(LastException)
 Else
  For i = 0 To Folders.Length - 1
   Log(Folders(i).Name)
   ftp2.Initialize("FTP","192.168.0.11","21","xxxxxx","xxxxxx")
   ftp2.TimeoutMs=30000
   ftp2.PassiveMode=True
   ftp2.List(root&Folders(i).Name)
  Next
 End If
End Sub
Sub ftp2_ListCompleted (ServerPath As String, Success As Boolean, Folders() As FTPEntry, Files() As FTPEntry)
 For Each f As FTPEntry In Files
  Log(f.Name)
 Next
End Sub
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
It needs more work as it will only read 1 sub folder deep from the root.

Probably best way would be to add all the folders to a list, then use that to read the files.
 
Upvote 0

Daestrum

Expert
Licensed User
Longtime User
After much trial and error (and learning how Wait For works)
This code will traverse any depth directories.
B4X:
#Region Project Attributes 
 #MainFormWidth: 600
 #MainFormHeight: 600 
#End Region
Sub Process_Globals
 Private fx As JFX
 Private MainForm As Form
 Dim FTP As FTP
 Dim root As String = "/GoFlex Home Public/Drive e/" ' case sensitive
 Dim filesList As List
 Dim lv As ListView
End Sub
Sub AppStart (Form1 As Form, Args() As String)
 MainForm = Form1
 MainForm.Show
 filesList.Initialize
 lv.Initialize("")
 MainForm.RootPane.AddNode(lv,10,10,580,500)
 FTP.Initialize("FTP","192.168.0.11",21,"xxxx","xxxxx")
 Wait For (getFolder(root)) Complete (r As Boolean)
 Log(filesList)
 Log("Completed")
End Sub
Sub getFolder (ServerFolder As String)As ResumableSub
 FTP.List(ServerFolder)
 Wait For FTP_ListCompleted (ServerPath As String, Success As Boolean, Folders() As FTPEntry, files() As FTPEntry) '<----
 If Success Then
  For Each f As FTPEntry In files
   filesList.Add(ServerPath&f.Name)
   lv.Items.Add(ServerPath&f.Name)
  Next
  If Folders.Length > 0 Then
   For Each f As FTPEntry In Folders
    Wait For (getFolder(ServerFolder&f.name&"/")) Complete (r As Boolean)
   Next
  End If
 Else
  Log($"Something broke :("$)
 End If
 Return True
End Sub
'Return true to allow the default exceptions handler to handle the uncaught exception.
Sub Application_Error (Error As Exception, StackTrace As String) As Boolean
 Return True
End Sub
 
Upvote 0
Top