Android Tutorial Android FTP tutorial

Status
Not open for further replies.
Old and irrelevant tutorial. Follow this one instead: [B4X] Net library (FTP, SMTP, POP) with Wait For

This tutorial covers the FTP object which is part of the Net library.
The Net library is based on Apache Commons Net.

Android OS doesn't allow us, the developers, to block the main thread for more than 5 seconds. When the main thread is busy for too long and is not able to handle the user events the "Application not responding" dialog appears.
Therefore slow operations like network operations should be done in the background.
The FTP library is built in such a way. All of the methods return immediately. When a task completes an event is raised. In fact you can submit several tasks one after another. The FTP protocol supports a single task at a time so the tasks will be processed serially.

Using the FTP library is pretty simple.
The first step is to initialize the FTP object. If this is an Activity module then you should do it in Activity_Create when FirstTime is true.
For Service modules it should be initialized in Service_Create.
B4X:
Sub Process_Globals
    Dim FTP As FTP
End Sub
Sub Globals

End Sub

Sub Activity_Create(FirstTime As Boolean)
    If FirstTime Then
        FTP.Initialize("FTP", "ftp.example.com", 21, "user", "password")
    End If
FTP.Initialize doesn't connect to the server. Connection will be established implicitly together with the next task.

Download

Downloading a file is done by calling DownloadFile with the remote file path and the local file path.
If you want to show the download progress then you should handle DownloadProgress event.
When download completes the DownloadCompleted event is raised. The ServerPath is passed as the first parameter to all events. You can use it to distinguish between different tasks. Make sure to check the Success parameter. If Success is False then you can find the exception message by calling LastException.

B4X:
    FTP.DownloadFile("/somefolder/files/1.zip", False, File.DirRootExternal, "1.zip")
   
Sub FTP_DownloadProgress (ServerPath As String, TotalDownloaded As Long, Total As Long)
    Dim s As String
    s = "Downloaded " & Round(TotalDownloaded / 1000) & "KB"
    If Total > 0 Then s = s & " out of " & Round(Total / 1000) & "KB"
    Log(s)
End Sub

Sub FTP_DownloadCompleted (ServerPath As String, Success As Boolean)
    Log(ServerPath & ", Success=" & Success)
    If Success = False Then Log(LastException.Message)
End Sub
Upload

Uploading is similar to downloading.
B4X:
    FTP.UploadFile(File.DirRootExternal, "1.txt", True, "/somefolder/files/1.txt")

Sub FTP_UploadProgress (ServerPath As String, TotalUploaded As Long, Total As Long)
    Dim s As String
    s = "Uploaded " & Round(TotalUploaded / 1000) & "KB"
    If Total > 0 Then s = s & " out of " & Round(Total / 1000) & "KB"
    Log(s)
End Sub

Sub FTP_UploadCompleted (ServerPath As String, Success As Boolean)
    Log(ServerPath & ", Success=" & Success)
    If Success = False Then Log(LastException.Message)
End Sub
List files and folders

FTP.List sends a request for the list of files and folders in a specific path.
The ListCompleted event is raised when the data is available.
You can use code similar to the following code to get more information on the entries:
B4X:
FTP.List("/")
...
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
Delete
Delete is done by calling FTP.Delete with the full path. Again an event will be raised when the task completes (DeleteCompleted).

Closing the connection
You can close the connection by calling FTP.Close. Close will wait for the other tasks to complete and then will close the connection. This happens in the background.
FTP.CloseNow will immediately close the connection, failing the remaining tasks.

Some notes:
- At any given time there should be less than 15 waiting tasks. Otherwise you will get a RejectedExecutionException (this happens when the internal threads pool is exhausted).
- The order of the completed tasks may be different than the order of submission.
- The AsciiFile parameters sets the file transfer mode. If AsciiFile is true then every occurrence of an end of line character will be translated based on the server native end of line character. If your FTP server is Unix or Linux then the end of line character is the same as Android.
In most cases you can set AsciiFile to false.

The library is available for download here: http://www.b4x.com/forum/additional...92-new-net-library-android-ftp-smtp-pop3.html
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
Hi all.

I'm doing some tests, using an emulator and my smartphone.

XAMPP-FILEZILLA on my pc.

User "home": C:\xampp\htdocs\AppTestUserDir

mFTPServerUserFolder = "/AppTestUserDir/"

Command: FTP.List(mFTPServerUserFolder)


Emulator (same using backslash \)
___________________________________________________________________________
Setting: mFTPServerUserFolder = "/"
(000001)30/10/2014 16:55:55 - (not logged in) (192.192.1.2)> 331 Password required for apptestuser
(000001)30/10/2014 16:55:55 - (not logged in) (192.192.1.2)> PASS **************
(000001)30/10/2014 16:55:55 - apptestuser (192.192.1.2)> 230 Logged on
(000001)30/10/2014 16:55:55 - apptestuser (192.192.1.2)> SYST
(000001)30/10/2014 16:55:55 - apptestuser (192.192.1.2)> 215 UNIX emulated by FileZilla
(000001)30/10/2014 16:55:55 - apptestuser (192.192.1.2)> PORT 10,0,2,2,252,192
(000001)30/10/2014 16:55:55 - apptestuser (192.192.1.2)> 200 Port command successful
(000001)30/10/2014 16:55:55 - apptestuser (192.192.1.2)> LIST /
(000001)30/10/2014 16:55:55 - apptestuser (192.192.1.2)> 150 Opening data channel for directory list.
(000001)30/10/2014 16:55:56 - apptestuser (192.192.1.2)> 425 Can't open data connection.
____________________________________________________________________________

Setting: mFTPServerUserFolder = "/AppTestUserDir/"
(000004)30/10/2014 17:05:23 - apptestuser (192.192.1.2)> LIST /AppTestUserDir/
(000004)30/10/2014 17:05:23 - apptestuser (192.192.1.2)> 550 Directory not found.
____________________________________________________________________________

C:\xampp\htdocs\AppTestUserDir contains one text file.



REAL DEVICE:
(RuntimeException) java.lang.RuntimeException: 530 User AppTestUser cannot log in.

Port 21 seems to be closed (tested from a site; the router admin console does not allow me to verify this)


Some help?


Thanks


[UPDATE] Using FTP.PassiveMode=True and the emulator the commands work.
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
I'm thinking that when I start a my b4J web server I need to open (and "link") a port (port forwarding) to allow a client to connect to the server ON MY PC.
Then che URL must be something like "xxx.xxx.xxx.xxx.pppp".

Since also my FTP server is on my pc, what should I do to allow a client to reach my server?


P.S. Opened, linked, NAT, port forwarding or whatelse is its name, 21 ---> my ftp server pc ip, nothing, the port seems to be still closed.


[SOLVED] Win7 Firewall was blocking the connection. Strangely, Comodo does not block it nor requests the permission, even though I have set this for each connection.
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
[SOLVED] Win7 Firewall was blocking the connection. Strangely, Comodo does not block it nor requests the permission, even though I have set this for each connection.

Solved (almost) nothing! :mad:

Situation:

Emulator: all ok

Device: (RuntimeException) java.lang.RuntimeException: AppTestUser 530 User can not log in.

Same app, changing only the address of the server (local in the emulator, public IP address in the device).

Port 21 is open !!!
 

LucaMs

Expert
Licensed User
Longtime User
Solved (almost) nothing! :mad:

Situation:

Emulator: all ok

Device: (RuntimeException) java.lang.RuntimeException: AppTestUser 530 User can not log in.

Same app, changing only the address of the server (local in the emulator, public IP address in the device).

Port 21 is open !!!


:eek::eek::eek::eek::eek::eek::eek:

This morning, turning on the smartphone, everything works fine.

Apparently it needed a reboot.

Mah!
 

wonder

Expert
Licensed User
Longtime User
Hello Erel,

I have a security question, I hope you can help me.

I compiled code below and decompiled the generated apk via http://www.decompileandroid.com.
B4X:
Sub Process_Globals
    Dim FTP As FTP
End Sub
Sub Globals

End Sub

Sub Activity_Create(FirstTime As Boolean)
    If FirstTime Then
        FTP.Initialize("FTP", "ftp.example.com", 21, "user", "password")
    End If
End Sub


When I opened the JAVA file "main.java" with Wordpad, I found this:

Capture.png


As you can see, it's fairly easy to obtain a developer's FTP password. :( Is there a solution for this problem? How can I use FTP in B4A without making my password public?
 
Last edited:

DonManfred

Expert
Licensed User
Longtime User
making my password public
It is not "public". You are doing illegal steps to reveal it.
You can ask the user for his ftp-login credentials and use his ftp then.
You should send files to your host in an other way. Using httputils and posting the file to an endpoint which gets the request and save the file.
 

wonder

Expert
Licensed User
Longtime User
You should send files to your host in an other way. Using httputils and posting the file to an endpoint which gets the request and save the file.
Thanks Manfred, I guess this covered in the HttpUtils tutorials, right? I'm not familiar with this method (yet).
All I want to do is upload game highscores to my server, as text files.

You can also use obfuscation to hide the strings: https://www.b4x.com/android/forum/threads/13773/#content (read carefully how strings are handled).

Strings obfuscation
Any string written in Process_Globals sub (and only in this sub) will be obfuscated, making it much harder to extract important keys. The strings are defuscated at runtime.
Note that several keys are used during obfuscation including the package name, version name and version code. Modifying these values with the manifest editor will break the defuscation process.
Thank you Erel, I will define the "password" in Process_Globals, repeat the compile/decompile test and see what comes up in the Java code. :)
 

luke2012

Well-Known Member
Licensed User
Longtime User
Hi @Erel,
I'm trying to write a file upload iteration and I wish to track the failed uploads in order to retry the upload process.

So for each iteration a call UploadFile and I track (see code belove) the failed uploads saving the ServerPath within a list.
At the end of the process I'll iterate on the list (if any failed upload exists) in order to retry the file upload.

Is this possibile having only the ServerPath information ? In other words : Can I retreive the file name to upload within ServerPath ?

B4X:
Sub ftpClient_UploadCompleted (ServerPath As String, Success As Boolean)
    if errList.isInitialized = false then errList.Initialize
  
    If Success = False Then
        errList.Add (ServerPath)
        Log(LastException.Message)
    end if
end sub
 

hibrid0

Active Member
Licensed User
Longtime User
Error Uploading files.

B4X:
Sub Button1_Click
Log("FTP2 Inicializado "&FTP2.IsInitialized)

    FTP2.SendCommand("MKD", "/NEW")
        FTP2.UploadFile (File.DirRootExternal, "logo_.png", False, "/")
End Sub

In b4a not show anything, the command MKD is excuted, but the file is not uploaded.

I see in the log of Filezilla Server and say:

B4X:
(000010)26/06/2015 05:34:45 a.m. - jose (192.168.0.10)> PORT 192,168,0,10,169,36
(000010)26/06/2015 05:34:45 a.m. - jose (192.168.0.10)> 200 Port command successful
(000010)26/06/2015 05:34:45 a.m. - jose (192.168.0.10)> STOR /
(000010)26/06/2015 05:34:45 a.m. - jose (192.168.0.10)> 550 Filename invalid
(000010)26/06/2015 05:36:46 a.m. - jose (192.168.0.10)> 421 Connection timed out.
(000010)26/06/2015 05:36:46 a.m. - jose (192.168.0.10)> disconnected.

The command excuted by B4A is "STOR /", not sent anything.

I'm testing in Filezilla server, but in first time I test with my hosting and not work.
 

DonManfred

Expert
Licensed User
Longtime User
From the tutorial in Post #1

B4X:
FTP.UploadFile(File.DirRootExternal, "1.txt", True, "/somefolder/files/1.txt")

the last parameter must be PATH INCLUDING FILENAME. Not just a Path.

->

B4X:
FTP2.UploadFile (File.DirRootExternal, "logo_.png", False, "/logo_.png")
 

hibrid0

Active Member
Licensed User
Longtime User
From the tutorial in Post #1

B4X:
FTP.UploadFile(File.DirRootExternal, "1.txt", True, "/somefolder/files/1.txt")

the last parameter must be PATH INCLUDING FILENAME. Not just a Path.

->

B4X:
FTP2.UploadFile (File.DirRootExternal, "logo_.png", False, "/logo_.png")
Hi bro thanks for the quick answer.
I see it in the post #220, I test and work now I'm testing the real server :-D

Now I dont see is the progress in the log...
With the download I see the progress but in upload not.
 

Prosg

Active Member
Licensed User
Longtime User
Hello,
I have success to ftp a .mp4 files... but the file is corrupt

what can i do pls... (but i don't want to zip :p)
 

arnold steger

Member
Licensed User
Longtime User
How is the position for insert the comand "FTP.DownloadFile("Namen/", True, PfadDownload,name)"?
Download file is generated whit 0 kB

B4X:
Sub ButtonUploadList_Click
    FTP.List("Namen/")
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
        ToastMessageShow(Folders,False)
        For i = 0 To Files.Length - 1
            Log(Files(i).Name & ", " & Files(i).Size & ", " & DateTime.Date(Files(i).Timestamp))
        Next
        ToastMessageShow(Files,False)
    End If
  
    If Success Then
    ToastMessageShow(ServerPath&Folders&" erfolgreich geladen",True)
    Else
    ToastMessageShow(ServerPath&" konnte nicht geladen werden",True)
    End If
  
End Sub
 
Last edited:

arnold steger

Member
Licensed User
Longtime User
i cannot see any download-command in your code
during the test of download i have insert in this methode.
B4X:
For i = 0To Files.Length - 1
Log(Files(i).Name & ", " & Files(i).Size & ", " & DateTime.Date(Files(i).Timestamp))
FTP.DownloadFile("Namen/", True, PfadDownload,name)
Next
 
Status
Not open for further replies.
Top