版权声明:本文为博主原创文章,未经博主同意不得转载。 https://blog.csdn.net/birdsaction/article/details/36379201

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

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

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

 

 

FTPCfg 用来存储ftp地址。password等信息的.

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有各种模式。这地方easy出错,导致无法获取到FTP上面的资源。

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

要依据FTP所在server的网络来设置,须要自己測试一下。

 

 

 

/**
*
*/
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进行下载文件的更多相关文章

  1. 【FTP】C# System.Net.FtpClient库连接ftp服务器(下载文件)

    如果自己单枪匹马写一个连接ftp服务器代码那是相当恐怖的(socket通信),有一个评价较高的dll库可以供我们使用. 那就是System.Net.FtpClient,链接地址:https://net ...

  2. (4)FTP服务器下载文件

    上一篇中,我们提到了怎么从FTP服务器下载文件.现在来具体讲述一下. 首先是路径配置.. 所以此处我们需要一个app.config来设置路径. <?xml version="1.0&q ...

  3. C#- FTP递归下载文件

    c# ftp递归下载文件,找来找去这个最好.(打断点,一小处foreach要改成for) /// <summary> /// ftp文件上传.下载操作类 /// </summary& ...

  4. Python之FTP多线程下载文件之分块多线程文件合并

    Python之FTP多线程下载文件之分块多线程文件合并 欢迎大家阅读Python之FTP多线程下载系列之二:Python之FTP多线程下载文件之分块多线程文件合并,本系列的第一篇:Python之FTP ...

  5. Python之FTP多线程下载文件之多线程分块下载文件

    Python之FTP多线程下载文件之多线程分块下载文件 Python中的ftplib模块用于对FTP的相关操作,常见的如下载,上传等.使用python从FTP下载较大的文件时,往往比较耗时,如何提高从 ...

  6. 如何在Linux中使用sFTP上传或下载文件与文件夹

    如何在Linux中使用sFTP上传或下载文件与文件夹 sFTP(安全文件传输程序)是一种安全的交互式文件传输程序,其工作方式与 FTP(文件传输协议)类似. 然而,sFTP 比 FTP 更安全;它通过 ...

  7. 通过cmd命令到ftp上下载文件

    通过cmd命令到ftp上下载文件 点击"开始"菜单.然后输入"cmd"点"enter"键,出现cmd命令执行框 2 输入"ftp& ...

  8. 访问FTP站点下载文件,提示“当前的安全设置不允许从该位置下载文件”的解决方案

    访问FTP站点下载文件,提示“当前的安全设置不允许从该位置下载文件”的解决方案: 打开客戶端浏览器--工具---internet-安全-自定义级别-选择到低到中低. 然后点受信任站点,把你要访问的站点 ...

  9. 26、android上跑apache的ftp服务

    一.为啥 在android设备跑ftp服务,在现场方便查看日志,目前就是这么用的. 二.前提: 从apache的官网下载依赖包:http://mina.apache.org/ftpserver-pro ...

随机推荐

  1. 关于python的元组操作

    关于元组: 元组和列表是类似的,但是元组中的数据是不可以修改的. 元组是一对 () 元组操作: 元组是不可以修改的所以对元组的操作极少 定义空元组(因为元组一旦创建,数据不可被修改,所以极少创建空元组 ...

  2. Orleans 整体介绍

    背景 Orleans 是微软开源的Actor模型开发框架. Actor模型 此模型解决了并发编程时对资源竞争使用的问题,将对同一个业务数据的访问从并行变为串行执行,降低了多线程编程的难度,使普通编程人 ...

  3. NKOJ3485 【2015多校联训4】数据

    问题描述 Mr_H 出了一道信息学竞赛题,就是给 n 个数排序.输入格式是这样的:试题有若干组数据.每组数据的第一个是一个整数 n,表示总共有 n 个数待排序:接下来 n 个整数,分别表示这n 个待排 ...

  4. 洛谷P1967 [NOIP2013提高组Day1T2]货车运输

    P1967 货车运输 题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过 ...

  5. 【模板】 递归线段树 [2017年五月计划 清北学堂51精英班Day4]

    P3372 [模板]线段树 1 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别 ...

  6. vue-li+webpack+iview构建项目步骤

    首先安装各类插件 npm install vue-cli -g vue init webpack demo npm install iview --save npm install less styl ...

  7. 低价替代Vector CANoe CAN总线适配解决方案支持所有USBCAN(周立功CAN、PCAN、Kvaser、ValueCAN、NI CAN)

    在汽车通信领域CAN总线使用非常广泛,最强大的工具有Vector Case(10WRMB).Pcan(2KRMB),ZLGCAN(1.5KRMB),KVASER(2KRMB).ValueCAN(4KR ...

  8. Eclipse Git插件切换分支的时候不要Reset

    今天做了一件蠢事,我在当前分支上改了很多代码,后来切换分支的时候,有一个文件有冲突,eclipse提示这个文件冲突,我可以选择commit/stash/reset,我一看这个文件没什么关系,不需要提交 ...

  9. js获取时间差值

    function GetTime(firstDate, secondDate) { // 1.对事件进行处理 var firsttime = Date.parse(firstDate + " ...

  10. DOM事件机制

    前言 本文主要介绍DOM事件级别.DOM事件模型.事件流.事件代理和Event对象常见的应用,希望对你们有些帮助和启发! 本文首发地址为GitHub博客,写文章不易,请多多支持与关注! 一.DOM事件 ...