Track FTP upload data in android?

2020-05-29 03:44发布

问题:

I have a working FTP system with android, but I want to be able to track the bytes as they get uploaded, so I can update a progress bar as the upload progresses. Is this possible with Android? Right now, I'm using org.apache.common.net.ftp and the code I'm using is below. Also, I am running this in an AsyncTask.

package com.dronnoc.ftp.complex;

import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.io.CopyStreamEvent;
import org.apache.commons.net.io.CopyStreamListener;
import org.apache.commons.net.io.Util;

import android.app.Activity;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.Window;

public class Main extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);


        setContentView(R.layout.main);

        String text = "BIGFILE"; //Big file here

        InputStream data = new ByteArrayInputStream(text.getBytes());

        new ComplexFTPTransfer().execute(data);
    }

    private class ComplexFTPTransfer extends AsyncTask<InputStream, Long[], Void>
    {
        private FTPClient ftp = null;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

            try {
                ftp = new FTPClient();
                ftp.connect("hostname");
            } catch (SocketException e) {
                this.cancel(true);
            } catch (IOException e) {
                this.cancel(true);
            }

            Main.this.setProgressBarIndeterminateVisibility(true);

        }


        @Override
        protected Void doInBackground(InputStream... params) {
            if(!this.isCancelled())
            {
                try 
                {
                    if(ftp.login("user", "pass"))
                    {
                        ftp.enterLocalPassiveMode();

                        InputStream item = params[0];

                        int streamSize = 0;
                        while(item.read() != -1)
                        {
                            streamSize++;
                        }

                        InputStream is = new BufferedInputStream(params[0], streamSize);
                        OutputStream os = ftp.storeFileStream("/test.txt");

                        Util.copyStream(is, os, streamSize, streamSize, new CopyStreamListener() {

                            @Override
                            public void bytesTransferred(long totalBytesTransferred, int bytesTransferred, long streamSize) {
                                publishProgress(new Long[] {totalBytesTransferred, streamSize});
                            }

                            @Override
                            public void bytesTransferred(CopyStreamEvent event) {

                            }
                        });
                        ftp.completePendingCommand();
                    }
                    ftp.logout();
                    ftp.disconnect();

                }
                catch (IOException e) {

                }
                catch (Exception e) {

                }
            }
            return null;
        }


        @Override
        protected void onProgressUpdate(Long[]... values) {
            super.onProgressUpdate(values);
            Log.d("UPDATE", values[0] + " of " + values[1] + " copied.");
            //TODO Put code here
        }

        @Override
        protected void onPostExecute(Void result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
            Main.this.setProgressBarIndeterminateVisibility(false);
        }
    }
}

What I want to know is if I can run a progress bar, updating every few uploaded bytes? Cheers

回答1:

This question has an implementation of an InputStream that includes a progress callback. Use that InputStream and call publishProgress from that callback for incremental updates during the file upload.



回答2:

Download this .jar file

httpmime-4.1.1.jar and commons-net.jar

        try {

            FTPClient ftpClient = new FTPClient();

            ftpClient.connect(InetAddress
                    .getByName(Your host Url));
            ftpClient.login(loginName, password);
            System.out.println("status :: " + ftpClient.getStatus());

            ftpClient.changeWorkingDirectory(your directory name);

            ftpClient.setFileType(FTP.IMAGE_FILE_TYPE);
                        //Your File path set here 
                        File file = new File("/sdcard/my pictures/image.png");  
            BufferedInputStream buffIn = new BufferedInputStream(
                    new FileInputStream(myImageFile));
            ftpClient.enterLocalPassiveMode();
            ProgressInputStream progressInput = new ProgressInputStream(
                    buffIn);

            boolean result = ftpClient.storeFile(UPLOADFILENAME + ".png",
                    progressInput);

            System.out.println("result is  :: " + result);
            buffIn.close();
            ftpClient.logout();
            ftpClient.disconnect();

        } catch (Exception e) {
            e.printStackTrace();

        }

//ProgressInputStream

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 * 40;

    private InputStream inputStream;
    //private Handler handler;

    private long progress;
    private long lastUpdate;

    private boolean closed;

    public ProgressInputStream(InputStream inputStream) {
        this.inputStream = inputStream;

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


回答3:

This can be done using Secure FTP Factory library.

You just need to implement an instance of the com.jscape.inet.ftp.FtpListener interface, register the instance with the Ftp class and overload the progress(FtpProgressEvent event) method to capture progress information.

JavaDoc: Overview (secure FTP Factory API)

Download: Java FTP, Java FTPS and Java SFTP Components



标签: java android ftp