Android中FTP服务器搭建、客户端编写_android设备代码搭建ftp服务器-程序员宅基地

技术标签: Android ftp服务器搭建  ftpclient  Android入门学习  ftpserver  

 

 最近一段时间,因为公司项目的需要,对HTTP协议以及FTP协议都有所了解,并且在基于网络开放源代码

  基础上,能够完成项目的要求。今天给大家分享下,怎样建立属于我们自己的FTP服务器以及FPT客户端,同时

  非常非常感谢这些开源软件及其作者为IT行业做出的贡献,最大程度上至少解放了我们这些IT码农。且看正文。


       本文主要内容:

                1、FTP服务端部署---- 基于Android中SwiFTP开源软件介绍;

                2、FTP客户端部署 --- 基于ftp4j开源jar包的客户端开发 ;

                3、使用步骤 --- 如何测试我们搭建的FTP可操作性。

 

       本文所涉及到的知识、文档、源代码照旧会在文章末尾列出。欢迎大家一起学习。

 


一、 FTP服务端部署


          SwiFTP开源软件是为Android系统开发,也就是说我们可以将其源代码嵌入到我们的项目中。当然,对其进行

  一定改造还是必不可少的。这儿只是从感官上对SwiFTP的运行效果图进行一下说面,以便帮助大家有初步认识:

         SwiFTP 资料信息:

                        Google Download 介绍 : http://code.google.com/p/swiftp/downloads/list

                                      GitHub 介绍 :        https://github.com/ppareit/swiftp

                 


                                                                                        

                                                                Android版本SwiFTP截图                                           

 

         界面其实很简单,但是从设计角度分析,SwiFTP框架系统还是值得我们研究的,当然如果你想改造成

  属于自己的FTP服务器(一般就是改改用户名、密码、PWD(起始工作目录))等,那更得花时间去钻研了。 

 


 二、 FTP客户端部署

    接下来,重点介绍我们的主角ftp4j开源jar包,该jar包就是开发我们FTP客户端核心了。

       ftp4j官网地址:http://www.sauronsoftware.it/projects/ftp4j/。对比与AndroidSDK而言,也就是ftp4j

   SDK了,一切的一切(文档、源代码、示例)都可以在官网查询 。想要了解的同学,至少得保证把首页给整明白吧。

 

  1、ftp4j概要

      官网描述如下:

           The ftp4j libraryimplementsa Java full-features FTP client. With ftp4j embedded in  your 

    application you  can :  FTP site (directory listing included), create, delete, transfer files

   (upload and download) , browse the remote FTP site (directory listing included), create, delete,

   rename and move remote directories and files.

 

   关于FTP连接主要有如下几种方式:

       The ftp4j library can connect the remote FTP server:

               · Througha direct TCP/IPconnection.        一般就是直接连接了。

               · Througha FTP proxy.                                    FTP代理

               · Tunnelling through a HTTPproxy.                 HTTP代理

               ·  Througha SOCKS 4/4aproxy.                    

               · Througha SOCKS 5 proxy.

               ·  You can add support to otherproxies plugging your own connector, since the ftp4jconnection manager

              architecture is modular.

 

 2、主要类简介

      下面根据官网的描述,将该ftp4j库的主要类简单说明下:


   FTPClient类

           该类封装了对FTPCommand的请求操作。例如:连接FTP服务器、进行各种各样的FTP操作(上传、下载、

     删除、重命名文件  等)。基本使用流程图如下:

                                                     

          利用伪代码描述如下:

[java]  view plain copy print ?
  1. //1、登录至FTPp服务器  
  2. mFTPClient.connect(mFTPHost, mFTPPort);  
  3. //2、请求授权  
  4. mFTPClient.login(mFTPUser, mFTPPassword);  
  5. //3、各种FTP操作  
  6. mFTPClient.upload();  
  7. mFTPClient.download();  
  8. //4、断开FTP连接  
  9. mFTPClient.disconnect();  
                   

     主要方法:

    public java.lang.String [] connect(java.lang.String host,    int port)   throws java.lang.IllegalStateException,

                                           java.io.IOException ,   FTPIllegalReplyException ,   FTPException

        功能:与FTP服务器主机建立连接 .

        参数 :

              host -   FTP服务器的主机名(host name) 或者 ip地址

              port -   FTP服务器的监听端口

       返回值 : The server welcome message ,FTP服务器响应消息

       抛出异常类型 :   (略,参见后文)

 

  public void login(java.lang.String username , java.lang.String password)   

                                         throws    java.lang.IllegalStateException,

                                                        java.io.IOException,  FTPIllegalReplyException,   FTPException

       功能:根据用户名以及密码登录FTP服务器

       参数:

             username – 登录FTP服务器的用户名.

             password - 登录FTP服务器的 密码

       返回值:(无)

       抛出异常类型  : (略,参见后文)

 

   public java.lang.String currentDirectory()    throws java.lang.IllegalStateException,   java.io.IOException,

                                                       FTPIllegalReplyException,    FTPException

       功能 :获取FTP服务器当前工作目录。

       返回值:FTP服务器当前工作目录

       抛出异常类型 : (略,参见后文)

 

  public long fileSize(java.lang.String path)

       功能:获取指定文件的大小。

       参数:

            path -- 指定文件所在的路径,可以是相对路径或者是绝对路径。

       返回值 : 指定文件的大小,单位为byte.

       抛出异常类型 :   (略,参见后文)

 

  public void deleteFile(java.lang.String path)  throws  java.lang.IllegalStateException,    java.io.IOException,

                                                         FTPIllegalReplyException,   FTPException

      功能:删除指定文件

      参数:

           path -- 指定文件所在的路径,可以使相对路径或者是绝对路径。

      返回值:(无)

      抛出异常类型 :   (略,参见后文)

 

   public void deleteDirectory(java.lang.String path)   throws java.lang.IllegalStateException,  

                                                         java.io.IOException,  FTPIllegalReplyException,   FTPException

      功能: 删除指定文件夹

      参数: 

          path -- 指定文件所在的路径,可以使相对路径或者是绝对路径。

      返回值:(无)

      抛出异常类型 :  (略,参见后文)

 

   public  FTPFile[] list()     throws java.lang.IllegalStateException ,  java.io.IOException,

      功能: 获取当前工作目录所有文件信息:文件名、文件大小、文件类型(文件或者文件夹)。

      返回值: FTPFile[]数组对象 ---- 该文件夹所对应的信息

      抛出异常类型 : (略,参见后文)


   public java.lang.String[] listNames()

      功能: 获取当前工作目录的所有文件名。

      返回值:String[]类型 ----- 所有文件名

      抛出异常类型 : (略,参见后文)


  public void upload(java.io.File file ,  FTPDataTransferListener listener)  throws java.lang.IllegalStateException,

                      java.io.FileNotFoundException,   java.io.IOException,    FTPIllegalReplyException,   FTPException,

                      FTPDataTransferException,  FTPAbortedException

 

      功能 :上传文件至FTP服务器。该操作会阻塞当前线程,阻塞会在操作完成后解除该方法可以通过调用

   abortCurrentDataTransfer()方法去中断。默认上传的文件目录是当前工作目录,通过currentDirectory()方法

   可以获得。注意:不支持上传文件夹。

     参数:file  -- 上传文件的File对象

              listener -- 监听器 (稍后介绍)

     抛出异常类型 : (略,参见后文)

 

  public void download(java.lang.String remoteFileName,    java.io.File localFile, 

                FTPDataTransferListener listener)

                                       throws java.lang.IllegalStateException,  java.io.FileNotFoundException,

                                                    java.io.IOException,   FTPIllegalReplyException,   FTPException,

                                                    FTPDataTransferException,  FTPAbortedException

       功能:下载某个文件值指定路径。该操作会阻塞当前线程,阻塞会在操作完成后解除。该方法可以通过调用

   abortCurrentDataTransfer()方法去中断。注意:不支持下载文件夹。

       参数:

            remoteFileName -  相对路径(相对于当前目录)时则是文件名或者绝对路径(例如:Linux中以”\”为前缀)

            localFile -  本地存放文件的File对象。

            listener -  监听器 (稍后介绍)

       抛出异常类型 : (略,参见后文)


   public void abortCurrentDataTransfer(boolean sendAborCommand)  throws java.io.IOException,  

                                                    FTPIllegalReplyException

      功能:如果存在任何正在进行的文件操作(上传/下载),该方法会中断它

      参数

         sendAborCommand --  true则代表中断文件操作,并且发送ABORT 命令给FTP服务器

                                          false 代表关闭中断文件操作,将不会发送任何消息给FTP服务器。

       抛出异常类型 : (略,参见后文)

 

  FTPFile 类

              该类封装了FTP服务器中文件的信息,即Model类。

 

     常量字段:   

                                                                                   文件对应类型

            public static final intTYPE_FILE                         文件

            public static final intTYPE_DIRECTORY            文件夹

            public static final intTYPE_LINK                       文件引用

 

    主要方法:

           public java.util.Date getModifiedDate()     获取文件最后修改日期。

           public int getType()                                  获取文件类型。

           public long getSize()                                 获取文件大小  ,单位为byte。

 

  FTPDataTransferListener   Interface 

        该接口约定了文件传输过程中的回调方法类型。我们可以实现该类去监听每个具体的文件操作过程。

  回调接口有:

           void started()            回调方法,表示已开始文件传输。

           void completed()        回调方法,表示文件传输已完成。

            void aborted()           回调方法,表示文件传输已被中断,可由abortCurrentDataTransfer()触发。

            void failed()              回调方法,表示文件传输由于某种错误而失败。

            void transferred(int length)  回调方法,表示本次回调过程中已下载/上传的文件字节大小。

               参数:  length --本次回调过程中下载/上传的文件字节大小。

               PS :我们可以累积length大小,以便获得当前文件已传输的字节数。

 

 异常种类:

            ftp4j的自定义共有如下几种,基本上每个FTP操作,都伴随着这些异常,因此,我们需要捕获这些异常信息。

 

   FTPAbortedException

         当文件传输过程被显示中断(例如,调用abortCurrentDataTransfer()方法)时,抛出该异常。

   FTPDataTransferException

         在文件传输过程中,发生任何I/O(例如,无法创建文件流)错误,都会抛出该异常。

   FTPException

         封装了FTP错误码以及错误消息的异常类。PS:类似于HTTP错误码以及错误消息

          常用方法:

            public int getCode()                    获取异常发生时,FTP的错误码(错误码字段值具体可见FTPCodes类)

            public java.lang.String getMessage()  获取异常发生时,FTP的错误消息。


   FTPIllegalReplyException

             当FTP服务器以一种非正常的方式---违反了FTP协议的规则响应时,抛出该异常。

   FTPListParseException

             通过list()方法请求FTP服务时,如果此时FTP服务器的返回的消息不能被正确的解析时,都会抛出该异常。



       通过对这些相关知识的学习,足矣利用ftp4j jar包完成我们简易却又充实的专属我们自己的FTP客户端了。

   接下来,便开始我们的FTP客户端的开发

 

   3、FTP客户端开发

       在功能需求上,开发一个FTP客户端和开发一个文件选择器甚至文件管理器基本上没有任何区别,唯一的区别

  只在于数据来源不同,这个不同会导致功能实践上更多细节的差异,例如:异常的捕获、断点尝试等。代码方面

  我就不再赘述了,对前面所介绍类的掌握和理解,应该No Problem了。主要说一下两点:

         ①、由于Android4.0不允许在主线程上进行网络操作,例如:Socket编程,我们的操作必须放在新的线程中。

    同时为了减少创建线程的开销,我们试用了线程池去执行每一个FTP操作。

         ②、试用FTPClient时,不允许上传/下载文件夹,我也没有针对这一方面进行更多的开发(具体实现过程大致

    为:对文件夹里的每个文件皆进行上传/下载操作),有兴趣的同学可以看看这篇帖子<基于ftp4j的FTP客户端工具>,

   会提升对你对ftp4j的使用认知的。

 

      我们的FTP客户端主要功能为:

          ①、显示特定目录列表;

          ②、删除文件以及文件夹,下载文件;

          ③、上传文件。

 

     主要代码如下:

[java]  view plain copy print ?
  1. /** 
  2.  *  
  3.  * @author jun.qin 
  4.  * {@link} http://blog.csdn.net/qinjuning 
  5.  * 
  6.  */  
  7. public class FtpMainActivity extends Activity implements OnClickListener {  
  8.   
  9.     private static String TAG = CopyOfFtpMainActivity.class.getName();  
  10.   
  11.     private CmdFactory mCmdFactory;  
  12.     private FTPClient mFTPClient;  
  13.     private ExecutorService mThreadPool;  
  14.       
  15.     @Override  
  16.     protected void onDestroy() {  
  17.         mDameonRunning = false ;  
  18.         Thread thread = new Thread(mCmdFactory.createCmdDisConnect()) ;  
  19.         thread.start();  
  20.         //等待连接中断  
  21.         try {  
  22.             thread.join(2000);  
  23.         } catch (InterruptedException e) {  
  24.             // TODO Auto-generated catch block  
  25.             e.printStackTrace();  
  26.         }  
  27.         mThreadPool.shutdownNow();  
  28.         super.onDestroy();  
  29.     }  
  30.     //put线程池中执行  
  31.     private void executeConnectRequest() {  
  32.         mThreadPool.execute(mCmdFactory.createCmdConnect());  
  33.     }  
  34.   
  35.     private void executeDisConnectRequest() {  
  36.         mThreadPool.execute(mCmdFactory.createCmdDisConnect());  
  37.     }  
  38.   
  39.     private void executePWDRequest() {  
  40.         mThreadPool.execute(mCmdFactory.createCmdPWD());  
  41.     }  
  42.   
  43.     private void executeLISTRequest() {  
  44.         mThreadPool.execute(mCmdFactory.createCmdLIST());  
  45.     }  
  46.     //创建FtpCmd的工厂类  
  47.     public class CmdFactory {  
  48.   
  49.         public FtpCmd createCmdConnect() {  
  50.             return new CmdConnect();  
  51.         }  
  52.   
  53.         public FtpCmd createCmdDisConnect() {  
  54.             return new CmdDisConnect();  
  55.         }  
  56.   
  57.     }  
  58.     //继承了Runnable接口  
  59.     public abstract class FtpCmd implements Runnable {  
  60.   
  61.         public abstract void run();  
  62.   
  63.     }  
  64.     //连接命令  
  65.     public class CmdConnect extends FtpCmd {  
  66.         @Override  
  67.         public void run() {  
  68.             boolean errorAndRetry = false ;  //根据不同的异常类型,是否重新捕获  
  69.             try {  
  70.                 String[] welcome = mFTPClient.connect(mFTPHost, mFTPPort);  
  71.                 if (welcome != null) {  
  72.                     for (String value : welcome) {  
  73.                         logv("connect " + value);  
  74.                     }  
  75.                 }  
  76.                 mFTPClient.login(mFTPUser, mFTPPassword);  
  77.                 mHandler.sendEmptyMessage(MSG_CMD_CONNECT_OK);  
  78.             }catch (IllegalStateException illegalEx) {  
  79.                 illegalEx.printStackTrace();  
  80.                 errorAndRetry = true ;  
  81.             }catch (IOException ex) {  
  82.                 ex.printStackTrace();  
  83.                 errorAndRetry = true ;  
  84.             }catch (FTPIllegalReplyException e) {  
  85.                 e.printStackTrace();  
  86.             }catch (FTPException e) {  
  87.                 e.printStackTrace();  
  88.                 errorAndRetry = true ;  
  89.             }  
  90.             if(errorAndRetry && mDameonRunning){  
  91.                 mHandler.sendEmptyMessageDelayed(MSG_CMD_CONNECT_FAILED, 2000);  
  92.             }  
  93.         }  
  94.     }  
  95.   
  96.     public class CmdDisConnect extends FtpCmd {  
  97.   
  98.         @Override  
  99.         public void run() {  
  100.             if (mFTPClient != null) {  
  101.                 try {  
  102.                     mFTPClient.disconnect(true);  
  103.                 } catch (Exception ex) {  
  104.                     ex.printStackTrace();  
  105.                 }  
  106.             }  
  107.         }  
  108.     }  
  109.     //下载命令  
  110.     public class CmdDownLoad extends AsyncTask<Void, Integer, Boolean> {  
  111.   
  112.         @Override  
  113.         protected Boolean doInBackground(Void... params) {  
  114.             try {  
  115.                 String localPath = getParentRootPath() + File.separator  
  116.                         + mFileList.get(mSelectedPosistion).getName();  
  117.                 mFTPClient.download(  
  118.                         mFileList.get(mSelectedPosistion).getName(),  
  119.                         new File(localPath),  
  120.                         new DownloadFTPDataTransferListener(mFileList.get(  
  121.                                 mSelectedPosistion).getSize()));  
  122.             } catch (Exception ex) {  
  123.                 ex.printStackTrace();  
  124.                 return false;  
  125.             }  
  126.   
  127.             return true;  
  128.         }  
  129.   
  130.         protected void onPostExecute(Boolean result) {  
  131.             toast(result ? "下载成功" : "下载失败");  
  132.             progressDialog.dismiss();  
  133.         }  
  134.     }  
  135. }  


三,使用方法说明

      前提条件, 确保两台手机分别安装FTP服务端,FTP客户端 ,并且能连接上WIFI网络。

   

    第一步:运行FTP服务器SwiFtp,输入基本信息(端口、用户名、密码),同时确保FTP服务器成功开启 。如图:

                                                           

                         配置FTP服务器信息                                                                                       FTP服务器状态


    第二步:运行FTP客户端,填写FTP验证时的资料(即第一步输入信息)后,连接FTP服务器即可。如图:


                                                                                            



      最后,本文所涉及到的所有资料以及文章中示例的源代码的下载地址为:


                          http://download.csdn.net/detail/qinjuning/5034873


文章地址:http://blog.csdn.net/qinjuning/article/details/8545601

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/adayabetter/article/details/43309781

智能推荐

使用nginx解决浏览器跨域问题_nginx不停的xhr-程序员宅基地

文章浏览阅读1k次。通过使用ajax方法跨域请求是浏览器所不允许的,浏览器出于安全考虑是禁止的。警告信息如下:不过jQuery对跨域问题也有解决方案,使用jsonp的方式解决,方法如下:$.ajax({ async:false, url: 'http://www.mysite.com/demo.do', // 跨域URL ty..._nginx不停的xhr

在 Oracle 中配置 extproc 以访问 ST_Geometry-程序员宅基地

文章浏览阅读2k次。关于在 Oracle 中配置 extproc 以访问 ST_Geometry,也就是我们所说的 使用空间SQL 的方法,官方文档链接如下。http://desktop.arcgis.com/zh-cn/arcmap/latest/manage-data/gdbs-in-oracle/configure-oracle-extproc.htm其实简单总结一下,主要就分为以下几个步骤。..._extproc

Linux C++ gbk转为utf-8_linux c++ gbk->utf8-程序员宅基地

文章浏览阅读1.5w次。linux下没有上面的两个函数,需要使用函数 mbstowcs和wcstombsmbstowcs将多字节编码转换为宽字节编码wcstombs将宽字节编码转换为多字节编码这两个函数,转换过程中受到系统编码类型的影响,需要通过设置来设定转换前和转换后的编码类型。通过函数setlocale进行系统编码的设置。linux下输入命名locale -a查看系统支持的编码_linux c++ gbk->utf8

IMP-00009: 导出文件异常结束-程序员宅基地

文章浏览阅读750次。今天准备从生产库向测试库进行数据导入,结果在imp导入的时候遇到“ IMP-00009:导出文件异常结束” 错误,google一下,发现可能有如下原因导致imp的数据太大,没有写buffer和commit两个数据库字符集不同从低版本exp的dmp文件,向高版本imp导出的dmp文件出错传输dmp文件时,文件损坏解决办法:imp时指定..._imp-00009导出文件异常结束

python程序员需要深入掌握的技能_Python用数据说明程序员需要掌握的技能-程序员宅基地

文章浏览阅读143次。当下是一个大数据的时代,各个行业都离不开数据的支持。因此,网络爬虫就应运而生。网络爬虫当下最为火热的是Python,Python开发爬虫相对简单,而且功能库相当完善,力压众多开发语言。本次教程我们爬取前程无忧的招聘信息来分析Python程序员需要掌握那些编程技术。首先在谷歌浏览器打开前程无忧的首页,按F12打开浏览器的开发者工具。浏览器开发者工具是用于捕捉网站的请求信息,通过分析请求信息可以了解请..._初级python程序员能力要求

Spring @Service生成bean名称的规则(当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致)_@service beanname-程序员宅基地

文章浏览阅读7.6k次,点赞2次,收藏6次。@Service标注的bean,类名:ABDemoService查看源码后发现,原来是经过一个特殊处理:当类的名字是以两个或以上的大写字母开头的话,bean的名字会与类名保持一致public class AnnotationBeanNameGenerator implements BeanNameGenerator { private static final String C..._@service beanname

随便推点

二叉树的各种创建方法_二叉树的建立-程序员宅基地

文章浏览阅读6.9w次,点赞73次,收藏463次。1.前序创建#include&lt;stdio.h&gt;#include&lt;string.h&gt;#include&lt;stdlib.h&gt;#include&lt;malloc.h&gt;#include&lt;iostream&gt;#include&lt;stack&gt;#include&lt;queue&gt;using namespace std;typed_二叉树的建立

解决asp.net导出excel时中文文件名乱码_asp.net utf8 导出中文字符乱码-程序员宅基地

文章浏览阅读7.1k次。在Asp.net上使用Excel导出功能,如果文件名出现中文,便会以乱码视之。 解决方法: fileName = HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8);_asp.net utf8 导出中文字符乱码

笔记-编译原理-实验一-词法分析器设计_对pl/0作以下修改扩充。增加单词-程序员宅基地

文章浏览阅读2.1k次,点赞4次,收藏23次。第一次实验 词法分析实验报告设计思想词法分析的主要任务是根据文法的词汇表以及对应约定的编码进行一定的识别,找出文件中所有的合法的单词,并给出一定的信息作为最后的结果,用于后续语法分析程序的使用;本实验针对 PL/0 语言 的文法、词汇表编写一个词法分析程序,对于每个单词根据词汇表输出: (单词种类, 单词的值) 二元对。词汇表:种别编码单词符号助记符0beginb..._对pl/0作以下修改扩充。增加单词

android adb shell 权限,android adb shell权限被拒绝-程序员宅基地

文章浏览阅读773次。我在使用adb.exe时遇到了麻烦.我想使用与bash相同的adb.exe shell提示符,所以我决定更改默认的bash二进制文件(当然二进制文件是交叉编译的,一切都很完美)更改bash二进制文件遵循以下顺序> adb remount> adb push bash / system / bin /> adb shell> cd / system / bin> chm..._adb shell mv 权限

投影仪-相机标定_相机-投影仪标定-程序员宅基地

文章浏览阅读6.8k次,点赞12次,收藏125次。1. 单目相机标定引言相机标定已经研究多年,标定的算法可以分为基于摄影测量的标定和自标定。其中,应用最为广泛的还是张正友标定法。这是一种简单灵活、高鲁棒性、低成本的相机标定算法。仅需要一台相机和一块平面标定板构建相机标定系统,在标定过程中,相机拍摄多个角度下(至少两个角度,推荐10~20个角度)的标定板图像(相机和标定板都可以移动),即可对相机的内外参数进行标定。下面介绍张氏标定法(以下也这么称呼)的原理。原理相机模型和单应矩阵相机标定,就是对相机的内外参数进行计算的过程,从而得到物体到图像的投影_相机-投影仪标定

Wayland架构、渲染、硬件支持-程序员宅基地

文章浏览阅读2.2k次。文章目录Wayland 架构Wayland 渲染Wayland的 硬件支持简 述: 翻译一篇关于和 wayland 有关的技术文章, 其英文标题为Wayland Architecture .Wayland 架构若是想要更好的理解 Wayland 架构及其与 X (X11 or X Window System) 结构;一种很好的方法是将事件从输入设备就开始跟踪, 查看期间所有的屏幕上出现的变化。这就是我们现在对 X 的理解。 内核是从一个输入设备中获取一个事件,并通过 evdev 输入_wayland

推荐文章

热门文章

相关标签