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:

biometrics

Active Member
Licensed User
Longtime User
Hi Erel,

Not sure I understand ... I am using a global variable. If I call FTP.List from Activity_Create and then let the Activity_Create finish and then wait for the event, how do I continue my code? Activity_Create has already ended. Keep in mind our application has no user interaction other then status feedback.

Could you perhaps demonstrate it with a short sample please.
 

biometrics

Active Member
Licensed User
Longtime User
You do not need to use a timer.
You should do something like:
B4X:
...
FTP.List

Sub ListCompleted(...)
 'continue your program flow
End Sub

Ah ok, thanks. That's an interesting approach. We do a lot of retries when things fail so a central Sub will work better in our case I think rather than chaining events.
 

nmoyer23

New Member
Licensed User
Longtime User
FTP download path

My FTP app works but I am having an issue creating a directory on the root of my sd card to download the file. When i pull the file from the FTP server, i'm not sure where the file ends up.
 

nmoyer23

New Member
Licensed User
Longtime User
FTP.DownloadFile("Test/teracopy.zip", False, File.DirRootExternal, "debug.txt")

I would like to change the path of the incoming file from my ftp server to the root of my sd card on my android phone.
 

AscySoft

Active Member
Licensed User
Longtime User
FTP.DownloadFile("Test/teracopy.zip", False, File.DirRootExternal, "debug.txt")

I would like to change the path of the incoming file from my ftp server to the root of my sd card on my android phone.

Sorry, I was out

You could try to create a folder first like this:
B4X:
'Create a folder (usually in /sdcard/temp/)
File.MakeDir (File.DirRootExternal,"temp")
'and then...
FTP.DownloadFile("Test/teracopy.zip", False, File.DirRootExternal & "/temp/", "debug.txt"
Be aware that your code will try to download "teracopy.zip" from your ftp server to a local folder under a different name "debug.txt"
You should download and save as zip file, then unzip it...
B4X:
'last line should be:
FTP.DownloadFile("Test/teracopy.zip", False, File.DirRootExternal & "/temp/", "teracopy.zip"
 
Last edited:

nmoyer23

New Member
Licensed User
Longtime User
That worked, thank you! I also need help connecting 3 text boxes (server, username and password) to the coding. I'm not sure how to do that.
 

AscySoft

Active Member
Licensed User
Longtime User
That worked, thank you! I also need help connecting 3 text boxes (server, username and password) to the coding. I'm not sure how to do that.

You should really check this thread first: http://www.b4x.com/forum/basic4andr...als/10407-android-ftp-tutorial.html#post57940

B4X:
'replace this with...
 FTP.Initialize("FTP", "ftp.example.com", 21, "user", "password")
'assuming your views (text boxes) are named server, username and password  
 FTP.Initialize("FTP", server.text, 21,  username.text, password.text)
 

sterlingy

Active Member
Licensed User
Longtime User
:sign0163:

This FTP code was very simple to implement. Worked on the first try, but there was one problem.

I am uploading jpegs to the server. In my test, the source photo from the phone is 564KB. On the FTP server, it is only 239KB. The file is not corrupt on the phone, but it is on the server.

On the other hand, uploading a TXT file worked perfectly.

Any thoughts?

UPDATE:

In the call, I changed the ASCII Boolean to FALSE. Now I get a proper image, but it never seems to be completely uploaded. See attached.
 
Last edited:

rfresh

Well-Known Member
Licensed User
Longtime User
There seems to be some kind of size limitation...is there an FTP upload size limit on your server?
 

sterlingy

Active Member
Licensed User
Longtime User
If there is a size limit, it isn't anything close to 1MB. I upload 100GB files all the time.

Also, I've noticed that most of the pictures I take with the phone are about 800KB, some of them seem to crap out at 150KB and others closer to the actual size of the original file.

I've noticed another thing. Sometimes the log says "Success" though the files are still corrupt. The other odd thing is that the log reports every byte being uploaded as it does its things, but it never says (for example) "Uploaded 764KB out of 834KB." I only get the "Uploaded 764KB"

-Sterling
 

sterlingy

Active Member
Licensed User
Longtime User
For those following my image upload problem, I've been trying different things with no success, but I did just get this error in my log:

"org.apache.commons.net.io.CopyStreamException: IOException caught while copying."

Maybe that will help the brilliant people solve this problem.

Sterling
 

AscySoft

Active Member
Licensed User
Longtime User
For those following my image upload problem, I've been trying different things with no success, but I did just get this error in my log:

"org.apache.commons.net.io.CopyStreamException: IOException caught while copying."

Maybe that will help the brilliant people solve this problem.

Sterling

I'm not one of them, I assure you, but did you tried with different type of files?
Try with some text files first, then with some 2-4MB PDF files, just report back!
 

sterlingy

Active Member
Licensed User
Longtime User
I'm not one of them, I assure you, but did you tried with different type of files?
Try with some text files first, then with some 2-4MB PDF files, just report back!

AscySoft,

I tried to FTP with a 3MB PDF, and a 2.5MB TXT file. Neither worked. I had tried a 17KB TXT file yesterday, and that worked, but I'm assuming that it was because the file was so small.

One thing to keep in mind is that if I try to upload the same file thee different times, it will upload a different amount each time, so that tells me there is no file size limit. Also, it's my server, and when I set up the account for this project, I did not specify a file size limit.

Lastly, I should point out that if I use Filezilla, I can upload these files without a problem.

Cheers,

Sterling :BangHead:
 

AscySoft

Active Member
Licensed User
Longtime User
AscySoft,
One thing to keep in mind is that if I try to upload the same file thee different times, it will upload a different amount each time, so that tells me there is no file size limit. Also, it's my server, and when I set up the account for this project, I did not specify a file size limit.

Lastly, I should point out that if I use Filezilla, I can upload these files without a problem.
Sterling :BangHead:

I also work with FileZilla with no problem... as a suggestion try to make your file encrypted and then uploaded... just in case somebody is listening on your 21 port!
 

sterlingy

Active Member
Licensed User
Longtime User
Are you using .Passive mode?

I don't no what mode B4A FTP library uses, nor do I know how to set the mode. When I use Filezilla, it is set to Passive mode.
 

sterlingy

Active Member
Licensed User
Longtime User
I also work with FileZilla with no problem... as a suggestion try to make your file encrypted and then uploaded... just in case somebody is listening on your 21 port!

You may be confused. I used Filezilla to make sure that my FTP server wasn't the problem. If you mean encrypt the files before uploading from my app, I don't know how to do that.

-Sterling
 
Status
Not open for further replies.
Top