一篇搞定安卓FTP登录/上传/下载/删除

1、前期准备
2、登录
3、上传
4、下载
5、删除
6、常用的一些方法

1、前期准备

一般自己搭建FTP服务器采用第三方的软件:Serv-U 或Xlight FTP Server,也可以自己在电脑上搭建。
在实际使用时需要先下载commons-net-3.3.jar包,本文中的事例代码已封装成FTPutils类,读者实际使用,可直接下载。
①:下载jar包:commons-net-3.3.jar
②:在AM中添加权限(如果是6.0及以上需要动态申请):

<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permissionandroid:name="android.permission.INTERNET"/>
<uses-permissionandroid:name="android.permission.READ_EXTERNAL_STORAGE"/>

2、登录

一般针对FTP都是抽取为一个工具类使用,对于一些参数的初始化设置,都是在其构造方法中完成,主要包括以下操作:
① 参数初始化

 public void useCompressedTransfer() {
        try {
            mFtpClient.setFileTransferMode(org.apache.commons.net.ftp.FTP.COMPRESSED_TRANSFER_MODE);
            // 使用被动模式设为默认
            mFtpClient.enterLocalPassiveMode();
            // 二进制文件支持
            mFtpClient.setFileType(FTP.BINARY_FILE_TYPE);
            //设置缓存
            mFtpClient.setBufferSize(1024);
            //设置编码格式,防止中文乱码
            mFtpClient.setControlEncoding("UTF-8");
            //设置连接超时时间
            this.mFtpClient.setConnectTimeout(10 * 1000);
            //设置数据传输超时时间
//            mFtpClient.setDataTimeout(10*1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

②登录

 public boolean connect(String ip, int port,String userName, String pass)  {
        boolean status = false;

        try {
            if(!mFtpClient.isConnected()){
                mFtpClient.connect(ip,port);
                status = mFtpClient.login(userName, pass);
                Constant.ftpLoginResult = status;
            }

            Log.i(TAG, "connect: " + status);
        } catch (IOException e) {
            e.printStackTrace();
        }

        return status;
    }

3、上传

①:通过流上传文件

 public void uploadFile(final InputStream srcFileStream, final String name)  {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    File file = new File( name );
                    mFtpClient.setFileType(FTP.BINARY_FILE_TYPE);    //图片支持二进制上传  如果采用ASCII_FILE_TYPE(默认),虽然上传后有数据,但图片无法打开
                    boolean status = mFtpClient.storeFile(name, srcFileStream);
                    srcFileStream.close();
                } catch (Exception e) {
                    Log.i(TAG, "run: "+e.toString());
                }
            }
        }).start();
    }

注意: 图片支持二进制上传在setFileType时如果采用ASCII_FILE_TYPE(默认),虽然上传后有数据,但图片无法打开。
②:通过URI方式

 public void uploadFile(String uri, String name) throws Exception {
        try {
            File file = new File(uri);
            mFtpClient.setFileType(org.apache.commons.net.ftp.FTP.BINARY_FILE_TYPE);
            FileInputStream srcFileStream = new FileInputStream(file);
            boolean status = mFtpClient.storeFile(name, srcFileStream);
            srcFileStream.close();
        } catch (Exception e) {
            throw e;
        }
    }

③:上传至FTP指定文件夹中

 /**
     * FTP上传文件
     * filePathName 文件路径方式
     * @param filePathName
     * @return
     */
    public boolean  ftpUploadFile(String filePathName){
        boolean result = false;
        try {
            File file = new File( filePathName );
            String  dataDirectory = file.getName().substring(0,8);
            if (file.exists()) {
                FileInputStream fileInputStream = new FileInputStream(file);
                 uploadDirectoryFile(fileInputStream, dataDirectory, file.getName());
                result = true;  //上传成功
            } else {
                Log.i(TAG, "ftpUploadFile: 文件路径不存在");
            }
        } catch (Exception e) {
            Log.i(TAG, "ftpUploadFile: "+"Failure : " + e.getLocalizedMessage());
        }
        return result ;
    }

    /**
     * 上传文件夹
     *文件流 上传后指定根目录 文件名称
     * @param srcFileStream   文件流
     * @param directoryName   ftp存储的文件夹名称
     * @param name            ftp存储的文件名称
     * @throws Exception
     */
    public void uploadDirectoryFile(InputStream srcFileStream, String directoryName, String name) throws Exception {
        try {
            mFtpClient.setFileType(org.apache.commons.net.ftp.FTP.BINARY_FILE_TYPE);
             //判断当前FTP工作目录
            String pwd = mFtpClient.printWorkingDirectory();
            if(pwd!=null){
                if(!("/"+Constant.ftpDirectoryFile).equals(pwd)){
                    getDirectoryExist(Constant.ftpDirectoryFile);
                }
            }
             getDirectoryExist(directoryName);
             mFtpClient.storeFile(name, srcFileStream)
            changeToParentDirectory();     
            srcFileStream.close();
        } catch (Exception e) {
            throw e;
        }
    }

注意:在文件上传中需要注意,在FTP默认上传的根目录是服务器的根目录文件夹下,如果我们需要根据业务需要重置文件夹路径,就需要以下几步:
第一:查看根目录指定文件夹是否存在

mFtpClient.makeDirectory(dir)

第二:如果存在就将当期的上传目录。切换至需要保存的文件夹目录中

mFtpClient.changeWorkingDirectory(DirectoryName)

以上两步也是getDirectoryExist(directoryName)方法完成的事情,确定好当前的上传目录是我们需要保存的目录后,就可以执行mFtpClient.storeFile(name, srcFileStream)操作。
重点强调一下,在实际使用中,比如我们需要按照日期来上传文件,此时需要按照日期来创建文件夹并将相应的内容存储在该文件夹下,这里需要特别注意WorkingDirectory的概念,最好实际打印出该文件夹名称,否则容易导致上传的内容和创建的文件夹混乱情况。
4、下载

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

        listener.onFtpProgress(Constant.FTP_CONNECT_SUCCESS, 0, null);

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

        // 创建本地文件夹
        File mkFile = new File(localPath);
        if (!mkFile.exists()) {
            boolean ismake=mkFile.mkdirs();
            Log.i(TAG,"是否存在"+ismake);
        }
        localPath = localPath + File.separator+fileName;
        // 接着判断下载的文件是否能断点下载
        long serverSize = files[0].getSize(); // 获取远程文件的长度
        File localFile = new File(localPath);
        long localSize = 0;
        if (localFile.exists()) {
            localSize = localFile.length(); // 如果本地文件存在,获取本地文件的长度
            if (localSize >= serverSize) {
                listener.onFtpProgress(Constant.LOCAL_FILE_AIREADY_COMPLETE, 0, localFile);
                localFile.delete();
                localFile.createNewFile();
                localSize=0;

            }else {
                listener.onFtpProgress(Constant.FTP_DOWN_CONTINUE, 0, null);
            }
        }else {
            localFile.createNewFile();

        }

        // 进度
        long step = serverSize / 100;
        long process = 0;
        long currentSize = localSize;
        // 开始准备下载文件
        OutputStream out = new FileOutputStream(localFile, true);
        mFtpClient.setRestartOffset(localSize);
        InputStream input = mFtpClient.retrieveFileStream(serverPath);//在调用此方法后,一定要在流关闭后再调用completePendingCommand结束整个事务
        byte[] b = new byte[1024];
        int length = 0;
        while ((length = input.read(b)) !=-1) {
            Log.i(TAG, "downloadSingleFile:正在下载"+step);
            out.write(b, 0, length);
            currentSize = currentSize + length;
            if (currentSize / step != process) {
                process = currentSize / step;
                if (process % 1 == 0) { // 每隔%1的进度返回一次
                    listener.onFtpProgress(Constant.FTP_DOWN_LOADING, process, null);
                }
            }
     
        }
        Log.i(TAG, "downloadSingleFile: 下载完毕");
        out.flush();
        out.close();
        input.close();

        // 此方法是来确保流处理完毕,如果没有此方法,可能会造成现程序死掉
        if (mFtpClient.completePendingCommand()&&localFile.length()==serverSize) {
            listener.onFtpProgress(Constant.FTP_DOWN_SUCCESS, process, localFile);
        } else  if(localFile.length()!=serverSize){
            listener.onFtpProgress(Constant.FTP_DOWN_SIZEOUT,serverSize,localFile);
        }
        else {
            listener.onFtpProgress(Constant.FTP_DOWN_FAIL, 0, null);
        }

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

        return;
    }

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

        listener.onFtpDelete(Constant.FTP_CONNECT_SUCCESS);

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

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

        return;
    }

5、删除

/**
*删除Ftp下的文件.
*@paramserverPath
*Ftp目录及文件路径
*@paramlistener
*监听器
*@throwsIOException
*/
public void deleteSingleFile(String serverPath,FtpDeleteFileListenerlistener)throwsException{

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

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

return;
}

6、常用的一些方法

以下总结的9种小方法是在实际使用中经常用到的,将其提取便于调用。其中mFtpClient是指在建立好登录连接操作以后的FTPClient对象,实际使用时需要判断登录是否连接,对象是否为空等,当然也根据需要提取出FTPClient中的常用API抽取为实用的方法。
①获取根目录下所有文件的名称

public String[]listName()throwsException{
try{
return mFtpClient.listNames();
}catch(Exceptione){
throwe;
}}

② 获取根目录下所有文件的名称

public FTPFile[]listName(Stringfile)throws Exception{
try{
FTPFile[] ftpFiles = mFtpClient.listFiles(file);
return ftpFiles;
}catch(Exceptione){
throwe;}}

③ 断FTP中是否包含上传的文件夹

try{
booleanb=makeDir(DirectoryName);
mFtpClient.changeWorkingDirectory(DirectoryName);
}catch(Exceptione){
e.printStackTrace();
}

④ 获取FTP当前工作的根目录

public String getFTPfile(){
String FTPWorkingPath="";
try{
FTPWorkingPath=mFtpClient.printWorkingDirectory();
}catch(IOExceptione){
e.printStackTrace();
}
return FTPWorkingPath;
}

⑤ 更改文件的存储路径

public void ftputilsChangeWorkingDirectory(StringdirectoryName){
try{
mFtpClient.changeWorkingDirectory(directoryName);
}catch(IOExceptione){
e.printStackTrace();
}
}

⑥ 创建文件夹

public boolean makeDir(Stringdir)throwsException{
try{
Return mFtpClient.makeDirectory(dir);
}catch(Exceptione){
throwe;
}}

⑦ 更改至父目录下

public void changeToParentDirectory(){
try{
mFtpClient.changeToParentDirectory();
}catch(IOExceptione){
}}

⑧ 断开连接

public void disconnect(){
try{
if(mFtpClient!=null&&mFtpClient.isConnected()){
mFtpClient.logout();//退出
mFtpClient.disconnect();//断开
}}catch(Exceptione){
e.printStackTrace();
}}

⑨ 判断是否登录

public boolean isConnected(){

boolean connected=false;
if(mFtpClient!=null){
mFtpClient.isConnected();
}
return connected;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值