Android Apache common ftp开源库以及http区别分析

1、前言:

ftp开源库:Apache common ftp开源库上传文件到局域网的ftp上吧。开源库是commons-net-2.2.jar。包名是这样的:org.apache.commons.net.ftp.FTPClient;用这个框架也能可以上传,下载以及删除ftp服务器的文件的。我也是参考网上大神例子迅速在项目中使用,现在趁机会总结一下,以及我自已在此基础上再次封装的ftp使用类。

http开源库:之前开发的时候先是用到了http协议上传文件,删除文件等等,使用的开源库是AsyncHttpClient开源框架android-async-http。当时我应用的场景也是需要从服务器下载文件,上传文件,以及删除文件。下载文件,上传文件我用了android-async-http这个。然后下载是用了使用HttpURLConnection断点续传下载文件。就是组合起来用吧。详细连接:android
使用AsyncHttpClient框架上传文件以及使用HttpURLConnection下载文件

ftp的简单介绍:FTP是File Transportation Protocol(文件传输协议)的缩写。目前在网络上,如果你想把文件和其他人共享。最方便的办法莫过于将文件放FTP服务器上,然后其他人通过FTP客户端程序来下载所需要的文件。如同其他的很多通讯协议,FTP通讯协议也采用客户机 / 服务器(Client / Server )架构。用户可以通过各种不同的FTP客户端程序,借助FTP协议,来连接FTP服务器,以上传或者下载文件。一般是需要ip,端口,用户名,以及密码。

http的简单介绍:HTTP则是Hyper Text Transportation Protocol(超文本传输协议)的缩写。HTTP是一种为了将位于全球各个地方的Web服务器中的内容发送给不特定多数用户而制订的协议。也就是说,可以把HTTP看作是旨在向不特定多数的用户“发放”文件的协议。 HTTP使用于从服务器读取Web页面内容。Web浏览器下载Web服务器中的HTML文件及图像文件等,并临时保存在个人电脑硬盘及内存中以供显示。 使用HTTP下载软件等内容时的不同之处只是在于是否以Web浏览器显示的方式保存,还是以不显示的方式保存而已。结构则完全相同。因此,只要指定文件,任何人都可以进行下载。

我之前开发时候,是服务器那边开发人员,定义好接口以及接口需要携带的参数。我根据接口进行开发,我根据接口实现了用户的登录,注册,获取验证。以及后面的上传文件,删除服务器文件等等。需要参数看服务其那边怎么定义接口。

这里说一下TCP/IP连接:实际上socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API), 通过Socket,我们才能使用TCP/IP协议。TCP协议对应于传输层。在网络传输也是经常用到一块。socket连接开源库我就没用过。一般都是自已写就可以。如果有好用的,记得评论留下地址。

2、再次封装的CustomApacheFTPManage

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.LinkedList;
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;

public class CustomApacheFTPManage {

	public static String hostName = "";
	public static int serverPort = 1200;
	public static String userName = "";
	public static String password = "";
	private static FTPClient ftpClient = null;

	public static final String FTP_CONNECT_SUCCESSS = "FTP_CONNECT_SUCCESSS";
	public static final String FTP_CONNECT_FAIL = "FTP_CONNECT_FAIL";
	public static final String FTP_DISCONNECT_SUCCESS = "FTP_DISCONNECT_SUCCESS";
	public static final String FTP_FILE_NOTEXISTS = "FTP_FILE_NOTEXISTS";

	public static final String FTP_UPLOAD_SUCCESS = "FTP_UPLOAD_SUCCESS";
	public static final String FTP_UPLOAD_FAIL = "FTP_UPLOAD_FAIL";
	public static final String FTP_UPLOAD_LOADING = "FTP_UPLOAD_LOADING";

	public static final String FTP_DOWN_LOADING = "FTP_DOWN_LOADING";
	public static final String FTP_DOWN_SUCCESS = "FTP_DOWN_SUCCESS";
	public static final String FTP_DOWN_FAIL = "FTP_DOWN_FAIL";

	public static final String FTP_DELETEFILE_SUCCESS = "FTP_DELETEFILE_SUCCESS";
	public static final String FTP_DELETEFILE_FAIL = "FTP_DELETEFILE_FAIL";

	//用于单例模式
	public static CustomApacheFTPManage mCustomFTPManage = null;

	//单例模式获取实例
	public static CustomApacheFTPManage GetInstance() {
		if (mCustomFTPManage == null || ftpClient == null ) {
			mCustomFTPManage = new CustomApacheFTPManage();
			ftpClient = new FTPClient();
		}
		return mCustomFTPManage;
	}

	public CustomApacheFTPManage(){

	}

	public void setParameter(String strhostName,int nserverPort ,String struserName,String strpassword) {
		hostName = strhostName;
		serverPort = nserverPort;
		userName = struserName;
		password = strpassword;

	}

	// -------------------------------------------------------文件上传方法------------------------------------------------

	/**
	 * 上传单个文件.
	 *
	 * @param localFile
	 *            本地文件
	 * @param remotePath
	 *            FTP目录
	 * @param listener
	 *            监听器
	 * @throws IOException
	 */
	public void uploadSingleFile(File singleFile, String remotePath,CurrentTipListener listener) throws IOException {

		// 上传之前初始化
		this.uploadBeforeOperate(remotePath, listener);

		boolean flag;
		flag = uploadingSingle(singleFile, listener);
		// 上传完成之后关闭连接
		this.uploadAfterOperate(listener);
	}

	/**
	 * 上传多个文件.
	 *
	 * @param localFile
	 *            本地文件
	 * @param remotePath
	 *            FTP目录
	 * @param listener
	 *            监听器
	 * @throws IOException
	 */
	public void uploadMultiFile(LinkedList<File> fileList, String remotePath,CurrentTipListener listener) throws IOException {

		// 上传之前初始化
		if (uploadBeforeOperate(remotePath, listener)) {
			boolean flag;

			int n = 0;
			for (File singleFile : fileList) {
				flag = uploadingSingle(singleFile, listener);
				if (flag) {
					n ++;
				if (n == fileList.size())
					listener.onCurrentTipCallBack(FTP_UPLOAD_SUCCESS);
				} else {
					listener.onCurrentTipCallBack(FTP_UPLOAD_FAIL);
				}
			}

			// 上传完成之后关闭连接
			this.uploadAfterOperate(listener);
		};
	}

	/**
	 * 上传单个文件.
	 *
	 * @param localFile
	 *            本地文件
	 * @return true上传成功, false上传失败
	 * @throws IOException
	 */
	private boolean uploadingSingle(File localFile,CurrentTipListener listener) throws IOException {
		boolean flag = true;
		// 不带进度条的方式
		 // 创建输入流
		 InputStream inputStream = new FileInputStream(localFile);
		 // 上传单个文件
		 flag = ftpClient.storeFile(localFile.getName(), inputStream);
		 // 关闭文件流
		 inputStream.close();

		// 带有进度的方式
//		BufferedInputStream buffIn = new BufferedInputStream(
//				new FileInputStream(localFile));
//		ProgressInputStream progressInput = new ProgressInputStream(buffIn,
//				listener, localFile);
//		flag = ftpClient.storeFile(localFile.getName(), progressInput);
//		buffIn.close();

		return flag;
	}

	/**
	 * 上传文件之前初始化相关参数
	 *
	 * @param remotePath
	 *            FTP目录
	 * @param listener
	 *            监听器
	 * @throws IOException
	 */
	private boolean uploadBeforeOperate(String remotePath,CurrentTipListener listener) throws IOException {

		// 打开FTP服务
		try {
			this.openConnect();
			listener.onCurrentTipCallBack(FTP_CONNECT_SUCCESSS);
		} catch (IOException e1) {
			e1.printStackTrace();
			listener.onCurrentTipCallBack(FTP_CONNECT_FAIL);
			return false;
		}

		// 设置模式
		ftpClient.setFileTransferMode(org.apache.commons.net.ftp.FTP.STREAM_TRANSFER_MODE);
		// FTP下创建文件夹
		ftpClient.makeDirectory(remotePath);
		// 改变FTP目录
		ftpClient.changeWorkingDirectory(remotePath);
		return true;
	}

	/**
	 * 上传完成之后关闭连接
	 *
	 * @param listener
	 * @throws IOException
	 */
	private void uploadAfterOperate(CurrentTipListener listener)throws IOException {
		this.closeConnect();
	}

	// -------------------------------------------------------文件下载方法------------------------------------------------

	/**
	 * 下载单个文件,可实现断点下载.
	 *
	 * @param serverPath
	 *            Ftp目录及文件路径
	 * @param localPath
	 *            本地目录
	 * @param fileName
	 *            下载之后的文件名称
	 * @param listener
	 *            监听器
	 * @throws IOException
	 */
	public void downloadSingleFile(String serverPath, String localPath, String fileName, DownLoadProgressListener listener)
			throws Exception {

		// 打开FTP服务
		try {
			this.openConnect();
			listener.onDownLoadProgress(FTP_CONNECT_SUCCESSS, 0, null);
		} catch (IOException e1) {
			e1.printStackTrace();
			listener.onDownLoadProgress(FTP_CONNECT_FAIL, 0, null);
			return;
		}

		// 先判断服务器文件是否存在
		FTPFile[] files = ftpClient.listFiles(serverPath);
		if (files.length == 0) {
			listener.onDownLoadProgress(FTP_FILE_NOTEXISTS, 0, null);
			return;
		}

		//创建本地文件夹
		File mkFile = new File(localPath);
		if (!mkFile.exists()) {
			mkFile.mkdirs();
		}

		localPath = localPath + fileName;
		// 接着判断下载的文件是否能断点下载
		long serverSize = files[0].getSize(); // 获取远程文件的长度
		File localFile = new File(localPath);
		long localSize = 0;
		if (localFile.exists()) {
			localSize = localFile.length(); // 如果本地文件存在,获取本地文件的长度
			if (localSize >= serverSize) {
				File file = new File(localPath);
				file.delete();
			}
		}

		// 进度
		long step = serverSize / 100;
		long process = 0;
		long currentSize = 0;
		// 开始准备下载文件
		OutputStream out = new FileOutputStream(localFile, true);
		ftpClient.setRestartOffset(localSize);
		InputStream input = ftpClient.retrieveFileStream(serverPath);
		byte[] b = new byte[1024];
		int length = 0;
		while ((length = input.read(b)) != -1) {
			out.write(b, 0, length);
			currentSize = currentSize + length;
			if (currentSize / step != process) {
				process = currentSize / step;
				if (process % 5 == 0) {  //每隔%5的进度返回一次
					listener.onDownLoadProgress(FTP_DOWN_LOADING, process, null);
				}
			}
		}
		out.flush();
		out.close();
		input.close();

		// 此方法是来确保流处理完毕,如果没有此方法,可能会造成现程序死掉
		if (ftpClient.completePendingCommand()) {
			listener.onDownLoadProgress(FTP_DOWN_SUCCESS, 0, new File(localPath));
		} else {
			listener.onDownLoadProgress(FTP_DOWN_FAIL, 0, null);
		}

		// 下载完成之后关闭连接
		this.closeConnect();
		listener.onDownLoadProgress(FTP_DISCONNECT_SUCCESS, 0, null);

		return;
	}

	// -------------------------------------------------------文件删除方法------------------------------------------------

	/**
	 * 删除Ftp下的文件.
	 *
	 * @param serverPath
	 *            Ftp目录及文件路径
	 * @param listener
	 *            监听器
	 * @throws IOException
	 */
	public void deleteSingleFile(String serverPath, DeleteFileProgressListener listener)
			throws Exception {

		// 打开FTP服务
		try {
			this.openConnect();
			listener.onDeleteProgress(FTP_CONNECT_SUCCESSS);
		} catch (IOException e1) {
			e1.printStackTrace();
			listener.onDeleteProgress(FTP_CONNECT_FAIL);
			return;
		}

		// 先判断服务器文件是否存在
		FTPFile[] files = ftpClient.listFiles(serverPath);
		if (files.length == 0) {
			listener.onDeleteProgress(FTP_FILE_NOTEXISTS);
			return;
		}

		//进行删除操作
		boolean flag = true;
		flag = ftpClient.deleteFile(serverPath);
		if (flag) {
			listener.onDeleteProgress(FTP_DELETEFILE_SUCCESS);
		} else {
			listener.onDeleteProgress(FTP_DELETEFILE_FAIL);
		}

		// 删除完成之后关闭连接
		this.closeConnect();
		listener.onDeleteProgress(FTP_DISCONNECT_SUCCESS);

		return;
	}

	// -------------------------------------------------------打开关闭连接------------------------------------------------

	/**
	 * 打开FTP服务.
	 *
	 * @throws IOException
	 */
	public void openConnect() throws IOException {
		// 中文转码
		ftpClient.setControlEncoding("UTF-8");
		int reply; // 服务器响应值
		// 连接至服务器
		ftpClient.connect(hostName, serverPort);
		// 获取响应值
		reply = ftpClient.getReplyCode();
		if (!FTPReply.isPositiveCompletion(reply)) {
			// 断开连接
			ftpClient.disconnect();
			throw new IOException("connect fail: " + reply);
		}
		// 登录到服务器
		ftpClient.login(userName, password);
		// 获取响应值
		reply = ftpClient.getReplyCode();
		if (!FTPReply.isPositiveCompletion(reply)) {
			// 断开连接
			ftpClient.disconnect();
			throw new IOException("connect fail: " + reply);
		} else {
			// 获取登录信息
			FTPClientConfig config = new FTPClientConfig(ftpClient.getSystemType().split(" ")[0]);
			config.setServerLanguageCode("zh");
			ftpClient.configure(config);
			// 使用被动模式设为默认
			ftpClient.enterLocalPassiveMode();
			// 二进制文件支持
			ftpClient.setFileType(org.apache.commons.net.ftp.FTP.BINARY_FILE_TYPE);
		}
	}

	/**
	 * 关闭FTP服务.
	 *
	 * @throws IOException
	 */
	public void closeConnect() throws IOException {
		if (ftpClient != null) {
			// 退出FTP
			ftpClient.logout();
			// 断开连接
			ftpClient.disconnect();
		}
	}

	// ---------------------------------------------------上传、下载、删除监听---------------------------------------------

	/*
	 * 下载进度监听
	 */
	public interface DownLoadProgressListener {
		public void onDownLoadProgress(String currentStep, long downProcess, File file);
	}

	/*
	 * 文件删除监听
	 */
	public interface DeleteFileProgressListener {
		public void onDeleteProgress(String currentStep);
	}

	public interface CurrentTipListener {
		public void onCurrentTipCallBack(String currentStep);
	}

	//上传文件准备
	public void onUploadSFile(final LinkedList<File> upload,final CurrentTipListener listener) {
		//ftp服务器需要新建的文件夹名称
		final String strFTPpath = "/" + getCurrentDataTime("yyyyMMddHHmmss");
		new Thread(new Runnable() {
			@Override
			public void run() {
                try {
                	//需要上传的文件upload
                   	uploadMultiFile(upload, strFTPpath, listener);
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}).start();
	} 

	public String getCurrentDataTime(String string) {
	    Date date = new Date(System.currentTimeMillis());
	    SimpleDateFormat sdformat = new SimpleDateFormat(string);// 24小时制
	    String LgTime = sdformat.format(date);
	    return LgTime;
	}
}

记得加入使用网络的权限。

不同的连接,有不同的传输协议。

本文博客涉及的代码:点击下载

3、参考网址

android与服务器通信方式的区别

Android系列之网络(一)----使用HttpClient发送HTTP请求(通过get方法获取数据)

Android中FTP上传、下载(含进度)

时间: 2024-10-17 20:54:01

Android Apache common ftp开源库以及http区别分析的相关文章

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

在Android使用ftp下载资源 可以使用ftp4j组件,还可以用apache common net里面的ftp组件,这2个组件我都用过. 个人感觉Apache common net里面的组件比较好用一些,下面是一个实例. 项目中对ftp的使用进行了封装,添加了回调函数已经断点续传的方法. FTPCfg 用来存储ftp地址,密码等信息的. FTPClientProxy 只是个代理而已,里面主要封装了common ftp api IRetrieveListener做回调用的,比如用于是否下载完成

Android动态换肤开源库Colorful发布

最近本人需要用到夜间模式,但是经过一番搜索似乎并没有看到好的开源实现,看到有一个类似的库MultipleTheme,但是需要自定义所有要实现换肤功能的View,感觉比较麻烦.当发现现有的解决方案不能很好的解决问题时,往往只能自己实现,因此本人花了点时间简单弄了一个实现该功能的开源库,命名为Colorful. Colorful是基于Theme,无需重启Activity.无需自定义View,方便的实现日间.夜间模式,github地址为 https://github.com/bboyfeiyu/Col

Android开发之常用开源库直接拿来用

1.from  代码家 整理比较好的源码连接 *************************************************************************************************************************************************************************** http://blog.zhan-dui.com/?page_id=60 感谢 "代码家"整理 一.

android事件总线(eventbus)开源库发布

 AndroidEventBus 如果你不知道事件总线是什么,那么没有关系,下面我们先来看这么一个场景: 你是否在开发的过程中遇到过想在Activity-B中回调Activity-A中的某个函数,但Activity又不能手动创建对象来设置一个Listener什么的? 你是否想在某个Service中想更新Activity或者Fragment中的界面? 等等之类的组件之间的交互问题-- 一经思考,你会发现Android中的Activity, Fragment, Service之间的交互是比较麻烦的,

进阶篇-用户界面:6.android studio使用github开源库实现下拉刷新

说实话,这是我第一次这么正儿八经的用github开源库,之前一直在听一些大神对这个世界级的开源库赞不绝口,今天终于体会到了.由于下拉刷新的类库是在eclipse下开发完成的,而eclipse如何使用如果导入网上的教程都非常详细.昨天我试了半天发现由于自己对android studio还不是很熟悉,所以引用类库的时候发现无从下手.但是今天早晨起来我唯一想做的事就是一定要实现这个下拉刷新的效果.我去网上找android studio导入类库的教程,导入PullToRefresh的教程,但是网上用的都

Android Volley+OkHttp3+Gson 开源库的封装

博客将按照下面的步骤介绍Volley的重新封装: 1.OkHttp3的关于Volley的HttpStack实现 2.HttpRequest的实现和HttpListener回调监听的封装 3.Volley原始的Request的Wrap 4.各种方式的请求的重新实现 5.统一请求的实现 6.使用 所需依赖: compile 'com.android.volley:volley:1.0.0' compile 'com.squareup.okio:okio:1.7.0' compile 'com.squ

Android 轻量级ORM数据库开源框架ActiveAndroid 源码分析

ActiveAndroid 项目地址在https://github.com/pardom/ActiveAndroid 关于他的详细介绍和使用步骤 可以看下面两篇文章: https://github.com/pardom/ActiveAndroid/wiki http://www.future-processing.pl/blog/persist-your-data-activeandroid-and-parse/ 请确保你在阅读本文下面的内容之前 熟读上面的2篇文章.我不会再讲一遍如何使用这个框

android 在线升级借助开源中国App源码

http://www.cnblogs.com/luomingui/p/3949429.html android 在线升级借助开源中国App源码分析如下: 1: checkAppUpdate 检查是或需要升级 // 网络连接判断         if (appContext.isNetworkConnected()) {             // 检查新版本             if (appContext.isCheckUp()) {                    UpdateM

GitHub Top 100的Android开源库

本项目主要对目前 GitHub 上排名前 100 的 Android 开源库进行简单的介绍, 至于排名完全是根据GitHub搜索Java语言选择「Best Match」得到的结果,然后过滤了跟Android不相关的项目,所以排名并不具备任何官方效力,仅供参考学习,方便初学者快速了解当前一些流行的Android开源库. 1. React Native 这个是 Facebook 在 React.js Conf 2015 大会上推出的基于 JavaScript 的开源框架 React Native,