實現背景
近期接觸到一個需求,就是將文件從Android系統上傳到FTP服務器,雖然之前接觸過FTP服務器,了解基本的使用流程,但是將此流程從使用習慣轉化為代碼實現還是有一定難度的。但是基本的流程還是比較清楚的:
- 1.在Android手機上創建一個FTP客戶端
- 2.設置host及端口建立與FTP服務器的連接
- 3.使用用戶名和密碼登錄FTP服務器
- 4.更改目錄,將當前客戶端指向的服務端的文件夾從跟目錄調整到指定的目錄
- 5.上傳文件,並等待上傳完成的結果
- 6.斷開和FTP服務器的鏈接
代碼實現
1.創建FTP客戶端並定義相關的操作流程
public class FTPClientFunctions {
private static final String TAG = "FTPClientFunctions";
private FTPClient ftpClient = null; // FTP客戶端
/**
* 連接到FTP服務器
*
* @param host ftp服務器域名
* @param username 訪問用戶名
* @param password 訪問密碼
* @param port 端口
* @return 是否連接成功
*/
public boolean ftpConnect(String host, String username, String password, int port) {
try {
ftpClient = new FTPClient();
Log.d(TAG, "connecting to the ftp server " + host + " :" + port);
ftpClient.connect(host, port);
// 根據返回的狀態碼,判斷鏈接是否建立成功
if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
Log.d(TAG, "login to the ftp server");
boolean status = ftpClient.login(username, password);
/*
* 設置文件傳輸模式
* 避免一些可能會出現的問題,在這里必須要設定文件的傳輸格式。
* 在這里我們使用BINARY_FILE_TYPE來傳輸文本、圖像和壓縮文件。
*/
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
ftpClient.enterLocalPassiveMode();
return status;
}
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "Error: could not connect to host " + host);
}
return false;
}
/**
* 斷開ftp服務器連接
*
* @return 斷開結果
*/
public boolean ftpDisconnect() {
// 判斷空指針
if (ftpClient == null) {
return true;
}
// 斷開ftp服務器連接
try {
ftpClient.logout();
ftpClient.disconnect();
return true;
} catch (Exception e) {
Log.d(TAG, "Error occurred while disconnecting from ftp server.");
}
return false;
}
/**
* ftp 文件上傳
*
* @param srcFilePath 源文件目錄
* @param desFileName 文件名稱
* @param desDirectory 目標文件
* @return 文件上傳結果
*/
public boolean ftpUpload(String srcFilePath, String desFileName, String desDirectory) {
boolean status = false;
try {
FileInputStream srcFileStream = new FileInputStream(srcFilePath);
status = ftpClient.storeFile(desFileName, srcFileStream);
srcFileStream.close();
return status;
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "upload failed: " + e.getLocalizedMessage());
}
return status;
}
/**
* ftp 更改目錄
*
* @param path 更改的路徑
* @return 更改是否成功
*/
public boolean ftpChangeDir(String path) {
boolean status = false;
try {
status = ftpClient.changeWorkingDirectory(path);
} catch (Exception e) {
e.printStackTrace();
Log.d(TAG, "change directory failed: " + e.getLocalizedMessage());
}
return status;
}
}
2.完整的操作流程
// 網絡操作,但開一個線程進行處理
new Thread(new Runnable() {
@Override
public void run() {
// TODO 可以首先去判斷一下網絡
ftpClient = new FTPClientFunctions();
boolean connectResult = ftpClient.ftpConnect(FTP_SERVER, FTP_USERNAME, FTP_PASSWORD, FTP_PORT);
if (connectResult) {
boolean changeDirResult = ftpClient.ftpChangeDir("/**");
if (changeDirResult) {
boolean uploadResult = ftpClient.ftpUpload(sourceFilePath, descFileName, "");
if (uploadResult) {
Log.w(TAG, "上傳成功");
boolean disConnectResult = ftpClient.ftpDisconnect();
if(disConnectResult) {
Log.e(TAG, "關閉ftp連接成功");
} else {
Log.e(TAG, "關閉ftp連接失敗");
}
} else {
Log.w(TAG, "上傳失敗");
}
} else {
Log.w(TAG, "切換ftp目錄失敗");
}
} else {
Log.w(TAG, "連接ftp服務器失敗");
}
}
}).start();
3.FTP交互相關庫
commons-net-3.6.jar : Apache Commons Net 阿帕奇提供的常用的網絡交互的jar包。
支持以下協議:
- FTP/FTPS
- FTP over HTTP (experimental)
- NNTP
- SMTP(S)
- POP3(S)
- IMAP(S)
- Telnet
- TFTP
- Finger
- Whois
- rexec/rcmd/rlogin
- Time (rdate) and Daytime
- Echo
- Discard
- NTP/SNTP
在這里我們只用的了FTP協議。不得不說,庫使用起來還是相當方便的。
相關鏈接:http://commons.apache.org/proper/commons-net/