在Android使用ftp下载资源 可以使用ftp4j组件,还可以用apache common net里面的ftp组件,这2个组件我都用过。
个人感觉Apache common net里面的组件比较好用一些,下面是一个实例。
项目中对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