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);