Android中使用Apache common ftp进行下载文件

在Android使用ftp下载资源 可以使用ftp4j组件,还可以用apache common net里面的ftp组件,这2个组件我都用过。

个人感觉Apache common net里面的组件比较好用一些,下面是一个实例。

项目中对ftp的使用进行了封装,添加了回调函数已经断点续传的方法。

 

Android中使用Apache common ftp进行下载文件

 

FTPCfg 用来存储ftp地址,密码等信息的.

FTPClientProxy 只是个代理而已,里面主要封装了common ftp api


IRetrieveListener做回调用的,比如用于是否下载完成,是否有错误等 可以通知到UI层

FTPManager 调用主入口

 

/**
 * bufferSize default is 1024*4
 * 
 * @author gaofeng
 * 2014-6-18 
 */
public class FTPCfg {

	public FTPCfg() {
	}
	
	public int port;
	public int bufferSize = 1024 * 4;
	public String address;
	public String user;
	public String pass;

}


 

 

 

/**
 * 
 */
package com.birds.mobile.net.ftp;

import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import android.util.Log;
/**
 * @author gaofeng 2014-6-18
 */
public class FTPClientProxy {

	FTPClient ftpClient = new FTPClient();
	FTPCfg config;

	protected FTPClientProxy(FTPCfg cfg) {
		this.config = cfg;
	}

	public FTPCfg getConfig() {
		return config;
	}

	public boolean connect() {
		try {
			FTPClientConfig ftpClientConfig = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
			ftpClientConfig.setLenientFutureDates(true);
			ftpClient.configure(ftpClientConfig);
			ftpClient.connect(config.address, config.port);
			int reply = this.ftpClient.getReplyCode();
			if (!FTPReply.isPositiveCompletion(reply)) {
				return false;
			}
			return true;
		} catch (SocketException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}

	public boolean login() {
		if (!ftpClient.isConnected()) {
			return false;
		}
		try {
			boolean b = ftpClient.login(config.user, config.pass);
			if (!b) {
				return false;
			}
			ftpClient.setFileType(FTPClient.FILE_STRUCTURE);
			ftpClient.enterLocalPassiveMode(); // very important
//			ftpClient.enterLocalActiveMode();
//			ftpClient.enterRemotePassiveMode();
//			ftpClient.enterRemoteActiveMode(InetAddress.getByName(config.address), config.port); 
			ftpClient.setFileType(FTP.BINARY_FILE_TYPE);  
			return b;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}

	public FTPFile[] getFTPFiles(String remoteDir) {
		try {
			return ftpClient.listFiles(remoteDir);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	public FTPFile getFTPFile(String remotePath) {
		try {
			Log.d("","getFTPFile.........." + remotePath);
			FTPFile f = ftpClient.mlistFile(remotePath);
			return f;
		} catch (IOException e) {
			e.printStackTrace();
		}
		Log.d("","getFTPFile null..........");
		return null;
	}

	public InputStream getRemoteFileStream(String remotePath) {
		InputStream ios;
		try {
			ios = ftpClient.retrieveFileStream(remotePath);
			return ios;
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

	public void close() {
		if (ftpClient.isConnected()) {
			try {
				ftpClient.logout();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		try {
			ftpClient.disconnect();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public void setRestartOffset(long len) {
		ftpClient.setRestartOffset(len);//断点续传的position
	}

	public boolean isDone() {
		try {
			return ftpClient.completePendingCommand();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return false;
	}

}


ftp有各种模式,这地方容易出错,导致无法获取到FTP上面的资源。

LocalPassiveMode,LocalActiveMode
就是主动模式和被动模式

要根据FTP所在服务器的网络来设置,需要自己测试一下。

 

 

 

/**
 * 
 */
package com.birds.mobile.net.ftp;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import org.apache.commons.net.ftp.FTPFile;

import android.util.Log;

/**
 * @author gaofeng 2014-6-18
 */
public class FTPManager {

	FTPClientProxy ftpProxy;
	IRetrieveListener listener;
	volatile boolean isLogin = false;
	volatile boolean stopDownload = false;
	
	protected FTPManager(){
		
	}

	public FTPManager(FTPCfg cfg) {
		ftpProxy = new FTPClientProxy(cfg);
	}

	/**
	 * track listener for FTP downloading
	 * @param listener
	 */
	public void setListener(IRetrieveListener listener) {
		this.listener = listener;
	}

	/**
	 * stop download task if you set true
	 * @param stopDownload
	 */
	public void setStopDownload(boolean stopDownload) {
		this.stopDownload = stopDownload;
	}

	public FTPFile[] showListFile(String remoteDir) {
		return ftpProxy.getFTPFiles(remoteDir);
	}

	public boolean connectLogin() {
		boolean ok = false;
		if (ftpProxy.connect()) {
			ok = ftpProxy.login();
		}
		isLogin = ok;
		return ok;
	}

	/**
	 * 
	 * @param remoteDir of FTP
	 * @param name of file name under FTP Server's remote DIR.
	 * @return FTPFile
	 */
	public FTPFile getFileByName(String remoteDir, String name) {
		FTPFile[] files = showListFile(remoteDir);
		if (files != null) {
			for (FTPFile f : files) {
				if (name.equalsIgnoreCase(f.getName())) {
					return f;
				}
			}
		}
		return null;
	}
	
	public void download(String remotePath, String localPath, long offset) {
		listener.onStart();
		File f = new File(localPath);
		byte[] buffer = new byte[ftpProxy.getConfig().bufferSize];
		int len = -1;
		long now = -1;
		boolean append = false;
		InputStream ins = null;
		OutputStream ous = null;
		try {
			if (offset > 0) { //用于续传
				ftpProxy.setRestartOffset(offset);
				now = offset;
				append = true;
			}
			Log.d("", "downloadFile:" + now + ";" + remotePath);
			ins = ftpProxy.getRemoteFileStream(remotePath);
			ous = new FileOutputStream(f, append);
			Log.d("", "downloadFileRenew:" + ins);
			while ((len = ins.read(buffer)) != -1) {
				if (stopDownload) {
					break;
				}
				ous.write(buffer, 0, len);
				now = now + len;
				listener.onTrack(now);//监控当前下载了多少字节,可用于显示到UI进度条中
			}
			if (stopDownload) {
				listener.onCancel("");
			} else {
				if (ftpProxy.isDone()) {
					listener.onDone();
				} else {
					listener.onError("File Download Error", ERROR.FILE_DOWNLOAD_ERROR);
				}
			}

		} catch (IOException e) {
			e.printStackTrace();
			listener.onError("File Download Error:" + e, ERROR.FILE_DOWNLOAD_ERROR);
		} finally {
			try {
				ous.close();
				ins.close();
			} catch (Exception e2) {
			}
		}
	}

	public void download(String remotePath, String localPath) {
		download(remotePath, localPath, -1);
	}

	public void close() {
		ftpProxy.close();
	}

	public static class ERROR { //自己定义的一些错误代码
		public static final int FILE_NO_FOUNT = 9001;
		public static final int FILE_DOWNLOAD_ERROR = 9002;
		public static final int LOGIN_ERROR = 9003;
		public static final int CONNECT_ERROR = 9004;
	}
}


 

 回调函数

public interface IRetrieveListener {
	public void onStart();
	public void onTrack(long nowOffset);
	public void onError(Object obj, int type);
	public void onCancel(Object obj);
	public void onDone();
}


library用的是apache common net 3.3

 

测试代码放在附件里面,不是很完善,但基本可以用。

http://download.csdn.net/detail/birdsaction/7580539

 

 

 

 

Android中使用Apache common ftp进行下载文件,布布扣,bubuko.com

Android中使用Apache common ftp进行下载文件

上一篇:SharePoint Server 2010的移动设备配置方案


下一篇:别小看锤子,老罗真的很认真