Monday, December 31, 2012

Creating Android FTP client | FTP operations


Many programmers have the following questions in mind.
"How do I do FTP operations from my android app?"
"How can I write a simple FTP client?"
"I want to store my application data in a FTP link at runtime. How can I do it?"
"How to upload images from my Android app to an FTP server/host ?"

There are many FTP client apps available for Android. But that's not an in-app solution.

What I'm going to describe here is a very simple way to build an ftp client inbuilt into your app.
With this you would be able to download a file from ftp host / upload file to a ftp host etc.

Prerequisites:

1. You would need an ftp implementation. I use a library from apache commons project.
   Copy org.apache.commons.net_2.0.0.v200905272248.jar file to the libs/ folder of your android app code

2. You would need an ftp host and an account to access it. I use drivehq.com.
   drivehq.com provies 1 GB of free ftp space. All my sample codes are uploaded to the same ftp host.
   Once you have an account you would have an UID & PW to access the host.
   In the sample apps, I have mentioned it as FTP_UID and FTP_PW. Replace these with the actual uid&pw

3. Add permission to your Android manifest
   <uses-permission android:name="android.permission.INTERNET"></uses-permission>
 

Note: Do all the ftp operations on a separate thread. Do not block the UI thread.
All the following operations use the FTPClient class which is defined in the jar file.
The sample implementation can be found in my sample code: MyFTPClient.java
import import org.apache.commons.net.ftp.*;

Sample App: FTPTest

Connecting to a FTP host
      mFTPClient = new FTPClient();  
      // connecting to the host  
      mFTPClient.connect("ftp.drivehq.com", 21);  
       boolean status = mFTPClient.login("FTP_UID", "FTP_PW");  
       // now check the reply code, if positive mean connection success  
      if (FTPReply.isPositiveCompletion(mFTPClient.getReplyCode())) {  
           /* Set File Transfer Mode  
            *  
            * To avoid corruption issue you must specified a correct  
            * transfer mode, such as ASCII_FILE_TYPE, BINARY_FILE_TYPE,  
            * EBCDIC_FILE_TYPE .etc. Here, I use BINARY_FILE_TYPE  
            * for transferring text, image, and compressed files.  
            */  
           mFTPClient.setFileType(FTP.ASCII_FILE_TYPE);  
           mFTPClient.enterLocalPassiveMode();  
      }  

Disconnecting from a ftp host

      mFTPClient.logout();  
      mFTPClient.disconnect();  

Retrieving current FTP directory
 workingDir = mFTPClient.printWorkingDirectory();  

Change the ftp directory path
 mFTPClient.changeWorkingDirectory(directory_path);  

Download a file from ftp host
      FileOutputStream desFileStream = new FileOutputStream(desFilePath);;  
      status = mFTPClient.retrieveFile(srcFilePath, desFileStream);  
      desFileStream.close();  

Upload a file to an ftp host
      FileInputStream srcFileStream = context.openFileInput(srcFilePath);  
   status = mFTPClient.storeFile(desFileName, srcFileStream);  
      srcFileStream.close();  

Print files in list
      public void ftpPrintFilesList(String dir_path)  
      {  
        try {  
          FTPFile[] ftpFiles = mFTPClient.listFiles(dir_path);  
          int length = ftpFiles.length;  
          for (int i = 0; i < length; i++) {  
            String name = ftpFiles[i].getName();  
            boolean isFile = ftpFiles[i].isFile();  
            if (isFile) {  
              Log.i(TAG, "File : " + name);  
            }  
            else {  
              Log.i(TAG, "Directory : " + name);  
            }  
          }  
        } catch(Exception e) {  
          e.printStackTrace();  
        }  
      }   

Create a directory in ftp host
      boolean status = mFTPClient.makeDirectory(new_dir_path);  

Remove a directory in ftp host
      boolean status = mFTPClient.removeDirectory(dir_path);  

Remove a file in ftp host
      boolean status = mFTPClient.deleteFile(filePath);  

Rename a file in ftp host
      boolean status = mFTPClient.rename(from, to);  

38 comments:

  1. getting error

    //Error: could not connect to host ftp.drivehq.com

    ReplyDelete
    Replies
    1. Hi Giri,

      Are you ale to connect to ftp.drivehq.com on the browser?

      And where are you seeing this error?

      Delete
    2. I am not able to connect to ftp.drivehq.com and the error is shown in Eclipse Logcat. Please help.

      Delete
    3. Add Permision for Internet

      Delete
    4. This comment has been removed by the author.

      Delete
  2. This comment has been removed by the author.

    ReplyDelete
  3. salam syed kamal i need ur help can u help me plz

    ReplyDelete
  4. Hello;
    I use the same code, but my probleme is that I can Upload and remove but I can't download.

    ReplyDelete
    Replies
    1. I tried to run Ftptest on Eclipse. However, "Login to ftp", "Upload file to ftp" and "Disconnect from ftp" did not work, just "Exit" was done. Can you help me.

      Delete
  5. Hi bess i m also doing the same code can u share ur id?

    ReplyDelete
  6. Hi, can someone upload complete ADT Eclipse Project Format???
    Because its not running on my PC
    Thanks

    MANO whats your ID???

    ReplyDelete
  7. mahil post your id

    ReplyDelete
  8. Can anyone help how to count stream bytes while uploading and downloading a file. I have done my else coding, I will be grateful for your kind opinion.
    Feel free to ask me for help in android
    email ID: skystar.h8@gmail.com

    ReplyDelete
    Replies
    1. I tried to run Ftptest on Eclipse. However, "Login to ftp", "Upload file to ftp" and "Disconnect from ftp" did not work, just "Exit" was done. Can you help me.

      Delete
  9. How to calculate progress while uploading and downloading, I am developing android FTP Client. Share your knowledge

    ReplyDelete
  10. hello syed kamal...i need ur help regarding android in my project..it includes obex ftp...

    ReplyDelete
  11. mahil143@yahoo.com
    this is my ID MANO
    please email me and contact me

    ReplyDelete
  12. syed kamal i need your help, please help in my project, i am unable to build this ftp project, my id is ameensvet@yahoo.com, or please give me your id.
    thanks

    ReplyDelete
  13. very good work. Thank u)
    But in my Eclipse your project show me many mistakes)
    Can you help to solve this problem?
    My mail once2go@ukr.net///\\\
    i suppose you find a minutes for it)
    with best regards, Denys Karpov

    ReplyDelete
  14. Hello Syed,
    I am not able to connect to ftp server even same server is getting opened in browser.

    I have add "INTERNET" permission in manifest file also.

    The logcat displays below exception:

    07-03 16:15:18.182: W/System.err(13827): java.net.UnknownHostException: Unable to resolve host "": No address associated with hostname
    07-03 16:15:18.182: W/System.err(13827): at java.net.InetAddress.lookupHostByName(InetAddress.java:424)
    07-03 16:15:18.182: W/System.err(13827): at java.net.InetAddress.getAllByNameImpl(InetAddress.java:236)
    07-03 16:15:18.193: W/System.err(13827): at java.net.InetAddress.getByName(InetAddress.java:289)
    07-03 16:15:18.193: W/System.err(13827): at org.apache.commons.net.SocketClient.connect(SocketClient.java:189)
    07-03 16:15:18.193: W/System.err(13827): at org.apache.commons.net.SocketClient.connect(SocketClient.java:278)
    07-03 16:15:18.193: W/System.err(13827): at com.kova.callmergeappinstaller.SendFiles$1.run(SendFiles.java:36)
    07-03 16:15:18.193: W/System.err(13827): Caused by: libcore.io.GaiException: getaddrinfo failed: EAI_NODATA (No address associated with hostname)
    07-03 16:15:18.193: W/System.err(13827): at libcore.io.Posix.getaddrinfo(Native Method)
    07-03 16:15:18.193: W/System.err(13827): at libcore.io.ForwardingOs.getaddrinfo(ForwardingOs.java:59)
    07-03 16:15:18.193: W/System.err(13827): at java.net.InetAddress.lookupHostByName(InetAddress.java:405)
    07-03 16:15:18.193: W/System.err(13827): ... 5 more

    ReplyDelete
    Replies
    1. I tried to run Ftptest on Eclipse. However, "Login to ftp", "Upload file to ftp" and "Disconnect from ftp" did not work, just "Exit" was done. Can you help me.

      Delete
  15. Unfortunately, FtpTest has stoped

    Sed kamal am facing this error when i press connect button of TestFtp

    Please help me
    please

    ReplyDelete
  16. i am student of MIT and my last semester goes to end after some days i have submit my project "SMART PHONE FTP CLIENT" and i have no idea about it
    Please any one help me

    ReplyDelete
  17. I tried to run Ftptest on Eclipse. However, "Login to ftp", "Upload file to ftp" and "Disconnect from ftp" did not work, just "Exit" was done. Can you help me.

    BTW, I can access ftp.drivehq.com from browser.
    Best Regards

    ReplyDelete
  18. Hi,
    Thank you for providing tutorial.I'm able to connect to server but i can't able to show directories or file from the root directory .I'm using the Print files in list method from here so can you please help .I'm facing problem with that .Hope you understand

    Thank You.

    ReplyDelete
  19. 09-26 04:18:56.075: E/Trace(9053): error opening trace file: No such file or directory (2)
    09-26 04:18:56.925: D/AndroidRuntime(9053): Shutting down VM
    09-26 04:18:56.925: W/dalvikvm(9053): threadid=1: thread exiting with uncaught exception (group=0x40a71930)
    09-26 04:18:56.935: E/AndroidRuntime(9053): FATAL EXCEPTION: main
    09-26 04:18:56.935: E/AndroidRuntime(9053): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.testftp/com.example.testftp.MainActivity}: android.os.NetworkOnMainThreadException
    09-26 04:18:56.935: E/AndroidRuntime(9053): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2180)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at android.app.ActivityThread.access$600(ActivityThread.java:141)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at android.os.Handler.dispatchMessage(Handler.java:99)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at android.os.Looper.loop(Looper.java:137)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at android.app.ActivityThread.main(ActivityThread.java:5041)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at java.lang.reflect.Method.invokeNative(Native Method)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at java.lang.reflect.Method.invoke(Method.java:511)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at dalvik.system.NativeStart.main(Native Method)
    09-26 04:18:56.935: E/AndroidRuntime(9053): Caused by: android.os.NetworkOnMainThreadException
    09-26 04:18:56.935: E/AndroidRuntime(9053): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1117)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:84)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at libcore.io.IoBridge.connectErrno(IoBridge.java:127)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at libcore.io.IoBridge.connect(IoBridge.java:112)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at java.net.Socket.connect(Socket.java:842)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at org.apache.commons.net.SocketClient.connect(SocketClient.java:176)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at com.example.testftp.MainActivity.onCreate(MainActivity.java:26)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at android.app.Activity.performCreate(Activity.java:5104)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080)
    09-26 04:18:56.935: E/AndroidRuntime(9053): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144)
    09-26 04:18:56.935: E/AndroidRuntime(9053): ... 11 more

    ReplyDelete
  20. instead of using ftp.drivehq.com
    i want my pc to be the host and maintain a database for username and passwords
    can u please help me out doing this??

    ReplyDelete
  21. Great! its the first working sample I found in the net.
    Many thanks.

    ReplyDelete
  22. you can also download jar from http://www.dhanyals.com

    ReplyDelete
  23. I run the source code from you and its crushing when i hit connect and it crush after bwt 5 seconds

    ReplyDelete
  24. HI kamal ...i m using this code but I am not able to connect to ftp.drivehq.com and the error is shown in Eclipse Logcat. help m Please.

    ReplyDelete
  25. Hi, How to upload mulltiple files??

    ReplyDelete
  26. Hi kamal, that's so helpful for me. Thank you so much for that.
    FTP Hosting

    ReplyDelete
  27. Hi there, I used the entire code that you posted here but I faced a problem. Please help me for setup of FTP Hosting

    ReplyDelete
  28. This comment has been removed by the author.

    ReplyDelete
  29. Olá, estou com o mesmo erro...
    W/System.err: java.net.UnknownHostException: Unable to resolve host "ftp.51.222.9.87/grel/res/": No address associated with hostname
    W/System.err: at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:125)
    W/System.err: at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:74)
    at java.net.InetAddress.getByName(InetAddress.java:708)
    at org.apache.commons.net.SocketClient.connect(SocketClient.java:202)
    W/System.err: at br.com.simtk.simtkrelatorio.util.MyFTP.run(MyFTP.java:29)
    W/System.err: Caused by: android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname)
    at libcore.io.Posix.android_getaddrinfo(Native Method)
    at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:55)
    W/System.err: at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:106)

    Help, please!!

    ReplyDelete
  30. hello sir..
    the link of the implementation is not working pls fix
    <3

    ReplyDelete