Upload/Download file using FTP server in Android

 

Download Code

Upload/Download file is the common functionality which we would require in our most of the projects. So let’s get started with the implementation…

  • Download latest FTP supported library from here
  • Refer publicly accessible FTP Server from this link https://dlptest.com/ftp-test/ .  In this tutorial I used same FTP Test credentials which is mentioned on this site. (I am really thankful to DLPTest Site)
  • Create user interface for FTP credentials along with upload and download buttons.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="16dp"
    tools:context="com.supportmania.droidftp.MainActivity">

    <android.support.design.widget.TextInputLayout
        android:id="@+id/FTPHostTextInputLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:id="@+id/FTPHostEditText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="FTP Host (IP)" />

    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/usernameTextInputLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:id="@+id/usernameEditText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="FTP Username" />

    </android.support.design.widget.TextInputLayout>

    <android.support.design.widget.TextInputLayout
        android:id="@+id/passwordTextInputLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <EditText
            android:id="@+id/passwordEditText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="FTP Password" />

    </android.support.design.widget.TextInputLayout>

    <Button
        android:id="@+id/downloadButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:background="@color/colorAccent"
        android:text="Download"
        android:textColor="@android:color/white" />

    <Button
        android:id="@+id/uploadButton"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:background="@color/colorAccent"
        android:text="Upload"
        android:textColor="@android:color/white" />
</LinearLayout>
  • We will upload file from SD-Card for which we would require user run-time permission

MainActivity.java

private static final int STORAGE_PERMISSION_RC = 99;

private void requestPermission() {
    if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
            PackageManager.PERMISSION_GRANTED) {
        ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSION_RC);
        return;
    }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == STORAGE_PERMISSION_RC) {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            //permission granted  start reading
        } else {
            Toast.makeText(this, "No permission to read external storage.", Toast.LENGTH_SHORT).show();
        }
    }
}
  • Mention same permission in manifest

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.supportmania.droidftp">

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
  • Now initialize controls and handle click events of Upload/Download buttons. Here functions such as startUpload() and startDownload() are core functions to perform upload and download file on FTP server using FTP credentials which we will capture from user input.

MainActivity.java

package com.supportmania.droidftp;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.os.Environment;
import android.os.StrictMode;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

import java.io.File;

import it.sauronsoftware.ftp4j.FTPClient;
import it.sauronsoftware.ftp4j.FTPDataTransferListener;
import it.sauronsoftware.ftp4j.FTPFile;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    /*********  work only for Dedicated IP ***********/
    static String FTP_HOST = "ftp.dlptest.com";
    /*********  FTP USERNAME ***********/
    static String FTP_USER = "dlpuser@dlptest.com";
    /*********  FTP PASSWORD ***********/
    static String FTP_PASS = "eiTqR7EMZD5zy7M";
    EditText FTPHostEditText, usernameEditText, passwordEditText;
    Button downloadButton, uploadButton;
    private static final int STORAGE_PERMISSION_RC = 99;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setupUI();
        setListners();
        requestPermission();
    }

    private void setupUI() {
        FTPHostEditText = (EditText) findViewById(R.id.FTPHostEditText);
        usernameEditText = (EditText) findViewById(R.id.usernameEditText);
        passwordEditText = (EditText) findViewById(R.id.passwordEditText);
        downloadButton = (Button) findViewById(R.id.downloadButton);
        uploadButton = (Button) findViewById(R.id.uploadButton);
    }

    private void requestPermission() {
        if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE) !=
                PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, STORAGE_PERMISSION_RC);
            return;
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == STORAGE_PERMISSION_RC) {
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                //permission granted  start reading
            } else {
                Toast.makeText(this, "No permission to read external storage.", Toast.LENGTH_SHORT).show();
            }
        }
    }


    private void setListners() {
        downloadButton.setOnClickListener(this);
        uploadButton.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        FTP_HOST = FTPHostEditText.getText().toString();
        FTP_USER = usernameEditText.getText().toString();
        FTP_PASS = passwordEditText.getText().toString();
        switch (v.getId()) {
            case R.id.downloadButton:
                startDownload();
                break;
            case R.id.uploadButton:
                startUpload();
                break;
        }
    }

    /**
     * Code to upload file on FTP server
     */
    private void startUpload() {
        FTPClient client = new FTPClient();
        try {
            //You can either call startUpload function in AsyncTask or
            //you can add below ThreadPolicy below version 9
            if (android.os.Build.VERSION.SDK_INT > 9) {
                StrictMode.ThreadPolicy policy =
                        new StrictMode.ThreadPolicy.Builder().permitAll().build();
                StrictMode.setThreadPolicy(policy);
            }
            client.connect(FTP_HOST, 21);
            client.login(FTP_USER, FTP_PASS);
            client.setType(FTPClient.TYPE_BINARY);

            //Replace your local File path which you want to upload.
            File file = Environment.getExternalStorageDirectory();
            File textFile = new File(file.getAbsolutePath() + File.separator + "chapter.txt");
            client.upload(textFile, new MyTransferListener("Upload"));
        } catch (Exception e) {
            e.printStackTrace();
            try {
                client.disconnect(true);
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }

    /**
     * Code to download multiple files from directory present on FTP server
     */
    private void startDownload() {
        FTPClient ftp = new FTPClient();
        try {
            if (android.os.Build.VERSION.SDK_INT > 9) {
                StrictMode.ThreadPolicy policy =
                        new StrictMode.ThreadPolicy.Builder().permitAll().build();
                StrictMode.setThreadPolicy(policy);
            }
            ftp.connect(FTP_HOST, 21);
            ftp.login(FTP_USER, FTP_PASS);

            //If change occurs in particular language then first delete folder from sdcard, also pass which language contains change.
            File dirStructure = new File("/sdcard/Nikhil/Test/");
            deleteDirectory(dirStructure);

            //cross check folder deleted or not, if not exist then create same folder at same location,
            //So that entire new folder can be paste inside SWF_Content folder
            if (!dirStructure.isDirectory()) {
                dirStructure.mkdirs();
            }

            //fetch file contents from ftp directory
            FTPFile[] arrEnglishContent = ftp.list("ftp file path");
            //example:
            //FTPFile[] arrEnglishContent = ftp.list("FTPFolder/Sample/Main");

            //as per requirement apply some cases to download single file at time
            String fileName = "";
            File localFile = null;
            for (int i = 0; i < arrEnglishContent.length; i++) {
                int indexOFEqual = arrEnglishContent[i].toString().indexOf("=");
                int indexOfSWF = arrEnglishContent[i].toString().indexOf(".txt");
                fileName = arrEnglishContent[i].toString().substring(indexOFEqual + 1, indexOfSWF) + ".txt";
                //create file inside folder
                localFile = new File(dirStructure + "/" + fileName);
                localFile.createNewFile();
                System.out.println(fileName);
                String remoteFileName = ftp + fileName;
                ftp.download(remoteFileName, localFile, new MyTransferListener("Download"));
            }
        } catch (Exception e) {
            e.printStackTrace();
            try {
                ftp.disconnect(true);
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
    }


    public boolean deleteDirectory(File path) {
        if (path.exists()) {
            File[] files = path.listFiles();
            if (files == null) {
                return true;
            }
            for (int i = 0; i < files.length; i++) {
                if (files[i].isDirectory()) {
                    deleteDirectory(files[i]);
                } else {
                    files[i].delete();
                }
            }
        }
        return (path.delete());
    }

    private class MyTransferListener implements FTPDataTransferListener {

        private String task;

        public MyTransferListener(String task) {
            this.task = task;
        }

        @Override
        public void started() {
            Toast.makeText(MainActivity.this, "Started....", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void transferred(int i) {
            Toast.makeText(MainActivity.this, "Transferred....", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void completed() {
            Toast.makeText(MainActivity.this, task + " Completed Successfully...", Toast.LENGTH_LONG).show();
        }

        @Override
        public void aborted() {
            Toast.makeText(MainActivity.this, "Aborted....", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void failed() {
            Toast.makeText(MainActivity.this, "Failed....", Toast.LENGTH_SHORT).show();
        }
    }
}
  • You can also download single file from FTP Server like mentioned below
/**
 * Code to download single file from FTP server
 */
private void downloadSingleFile() {
    FTPClient ftp = new FTPClient();
    try {
        if (android.os.Build.VERSION.SDK_INT > 9) {
            StrictMode.ThreadPolicy policy =
                    new StrictMode.ThreadPolicy.Builder().permitAll().build();
            StrictMode.setThreadPolicy(policy);
        }
        ftp.connect(FTP_HOST, 21);
        //System.out.println(ftp.connect(host)[0]);
        ftp.login(FTP_USER, FTP_PASS);
        File fileDownload = new File("/sdcard/testnew.txt");
        fileDownload.createNewFile();
        ftp.download("sample.txt", fileDownload,
                new FTPDataTransferListener() {

                    public void transferred(int arg0) {
                        //download_btn.setVisibility(View.GONE);
                        Log.v("log_tag", "This is for tranfer");
                        Toast.makeText(getBaseContext(), " transferred ..." + arg0, Toast.LENGTH_SHORT).show();
                    }

                    public void started() {
                        Toast.makeText(getBaseContext(), " Upload Started ...", Toast.LENGTH_SHORT).show();
                        Log.v("log_tag", "This is for started");
                    }

                    public void failed() {
                        //download_btn.setVisibility(View.VISIBLE);
                        Toast.makeText(getBaseContext(), "  failed ...", Toast.LENGTH_SHORT).show();
                        System.out.println(" failed ...");
                    }

                    public void completed() {
                        //download_btn.setVisibility(View.VISIBLE);
                        Toast.makeText(getBaseContext(), " completed ...", Toast.LENGTH_SHORT).show();
                        Log.v("log_tag", "This is for completed");
                    }

                    public void aborted() {
                        //download_btn.setVisibility(View.VISIBLE);
                        Toast.makeText(getBaseContext(), " transfer aborted,please try again...", Toast.LENGTH_SHORT).show();
                        Log.v("log_tag", "This is for aborted");
                    }
                });
    } catch (Exception e) {
        e.printStackTrace();
        try {
            ftp.disconnect(true);
        } catch (Exception e2) {
            e2.printStackTrace();
        }
    }
}

I hope this article is pretty simple and explained very well about Shimmer library. If you have any queries, do post them in comments section below.

Leave a Reply

Be the First to Comment!

avatar
  Subscribe  
Notify of