Uploading a file to FTP with Android

At Integrum, we ran in to a situation where we had to upload a file from the Android file system to an FTP server. We found that documentation on the matter was rather sparse so I decided to post about our solution.

We ended up using the Apache commons-net-ftp library that can be found here: http://www.docjar.com/jar_detail/commons-net-ftp-2.0.jar.html

After adding that jar to the build path, the implementation was pretty straightforward:

import org.apache.commons.net.ftp.FTPClient;
 
FTPClient ftpClient = new FTPClient();
 
try {
    ftpClient.connect(InetAddress.getByName(SERVER));
    ftpClient.login(USERNAME, PASSWORD);
    ftpClient.changeWorkingDirectory(PATH);
 
    if (ftpClient.getReplyString().contains("250")) {
        ftpClient.setFileType(org.apache.commons.net.ftp.FTP.BINARY_FILE_TYPE);
        BufferedInputStream buffIn = null;
        buffIn = new BufferedInputStream(new FileInputStream(FULL_PATH_TO_LOCAL_FILE));
        ftpClient.enterLocalPassiveMode();
        ProgressInputStream progressInput = new ProgressInputStream(buffIn, progressHandler);
 
        boolean result = ftpClient.storeFile(localAsset.getFileName(), progressInput);
        buffIn.close();
        ftpClient.logout();
        ftpClient.disconnect();
    }
 
} catch (SocketException e) {
    Log.e(SorensonApplication.TAG, e.getStackTrace().toString());
} catch (UnknownHostException e) {
    Log.e(SorensonApplication.TAG, e.getStackTrace().toString());
} catch (IOException e) {
    Log.e(SorensonApplication.TAG, e.getStackTrace().toString());
}

The ProgressInputStream is a custom version of InputStream that takes an instance of android.os.Handler in constructer. the overridden read method sends an update to the Handler after every 10KB transfered (Thanks to Steven Schlansker on Stackoverflow). The following excerpt contains the general idea of how to pass information back to the UI thread.

package com.royvandewater.utils;
 
import java.io.IOException;
import java.io.InputStream;
 
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
 
public class ProgressInputStream extends InputStream {
 
    /* Key to retrieve progress value from message bundle passed to handler */
    public static final String PROGRESS_UPDATE = "progress_update";
 
    private static final int TEN_KILOBYTES = 1024 * 10;
 
    private InputStream inputStream;
    private Handler handler;
 
    private long progress;
    private long lastUpdate;
 
    private boolean closed;
 
    public ProgressInputStream(InputStream inputStream, Handler handler) {
        this.inputStream = inputStream;
        this.handler = handler;
 
        this.progress = 0;
        this.lastUpdate = 0;
 
        this.closed = false;
    }
 
    @Override
        public int read() throws IOException {
            int count = inputStream.read();
            return incrementCounterAndUpdateDisplay(count);
        }
 
    @Override
        public int read(byte[] b, int off, int len) throws IOException {
            int count = inputStream.read(b, off, len);
            return incrementCounterAndUpdateDisplay(count);
        }
 
    @Override
        public void close() throws IOException {
            super.close();
            if (closed)
                throw new IOException("already closed");
            closed = true;
        }
 
    private int incrementCounterAndUpdateDisplay(int count) {
        if (count > 0)
            progress += count;
        lastUpdate = maybeUpdateDisplay(progress, lastUpdate);
        return count;
    }
 
    private long maybeUpdateDisplay(long progress, long lastUpdate) {
        if (progress - lastUpdate > TEN_KILOBYTES) {
            lastUpdate = progress;
            sendLong(PROGRESS_UPDATE, progress);
        }
        return lastUpdate;
    }
 
    public void sendLong(String key, long value) {
        Bundle data = new Bundle();
        data.putLong(key, value);
 
        Message message = Message.obtain();
        message.setData(data);
        handler.sendMessage(message);
    }
}
    • dappa
    • March 12th, 2011

    Great tutorial, this is just what I was looking for. But I can’t get it working.

    In actual workable example, how do you iniate progressHandler and localAsset? I have tried this:

    Handler progressHandler = new Handler();

    In android manifest I have set:

    Do I need to add more permissions?

    How about adding fully working project files to this post?

  1. No trackbacks yet.