轉自: http://phenom.iteye.com/blog/1551554
java中的ftp4j是個不錯的框架,可以用於java實現ftp的一些操作。
這個框架已經實現了ftp的功能,如果需要移植到android,就需要一些界面元素與後臺進程。
android這樣直接利用現在的java框架完成一些事情是比較容易的。
ftp4j的文檔還是蠻全的,而且容易讀懂。
- 使用方法:
- FTPClient client = new FTPClient();
- client.connect("ftp.host.com", 8021);
- client.login("carlo", "mypassword");
- 沒有異常表示連接成功,否則會墊子拋出FTPException異常。
- 當然還有一些重載方法,如果端口爲21就可以用client.connect(host);
- 爲了處理匿名的登錄,可以client.login("anonymous", "ftp4j");,用戶名是anonymous,密碼隨意。
- 登錄之後需要對服務器進行操作,如目錄顯示,進入等;
- String dir = client.currentDirectory(); 顯示當前目錄
- 修改進入的目錄
- client.changeDirectory(newPath);
- 可以使用相對路徑,也可以使用絕對路徑,下面兩種都可以。
- client.changeDirectory("/an/absolute/one");
- client.changeDirectory("relative");
- 如果只想進入上一層:client.changeDirectoryUp();
- ftp4j中有兩個特別目錄“.","..",分別表示根目錄與上一層目錄。
- 重命名:client.rename("oldname", "newname");
- 或移動文件:client.rename("myfile.txt", "myfolder/myfile.txt");
- 刪除文件:client.deleteFile(relativeOrAbsolutePath);可以使用相對或絕對路徑。
- 創建目錄:client.createDirectory("newfolder");
- 刪除目錄:client.deleteDirectory(absoluteOrRelativePath);
- 顯示文件,目錄,鏈接
- 由於服務器的不同,所以返回的文件列表格式也不同,可能是UNIX,也可能是WIN的。ftp4j目錄支持:
- UNIX style and variants (i.e. MAC style)
- DOS style
- NetWare styles
- EPLF
- MLSD
- .顯示當前的目錄文件:FTPFile[] list = client.list();
- FTPFile包含了所需要的信息,從type可以知道是目錄還是文件,或鏈接。
- 除此外還可以過濾:
- FTPFile[] list = client.list("*.jpg");過濾了,只顯示圖片
- 如果想知道修改上期,需要單獨獲取,不能從上面的list()方法得到:
- java.util.Date md = client.modifiedDate("filename.ext");
- 接下來就是上傳與下載了:
- client.download("remoteFile.ext", new java.io.File("localFile.ext"));
- client.upload(new java.io.File("localFile.ext"));
- 追加內容的上傳
- client.append(new java.io.File("localFile.ext"));
- 這些是阻塞方法,只有在完成後才返回,所以一個FTPClient只能在同時進行一個傳輸。如果你想多個文件同時傳輸,可以使用多個FTPClient,FTPClient單獨連接服務器。
- 當今的軟件不能只是功能上實現了,還需要注意用戶體驗,所以上傳下下載需要知道進度,ftp4j都通過FTPDataTransferListener這個接口來實現的,如果有一個方法:
- public void transferred(int length) {
- // Yet other length bytes has been transferred since the last time this
- 這個方法是說在距上一次傳輸到這一次傳輸的內容多少,
- 如果要有一個進度條,需要知道總量,然後當前傳輸的量,所以需要進行一些處理,如在開始上傳時,獲取本地文件上傳大小,然後從這個接口中得到已經傳輸的文件疊加起來得到已經傳輸文件總量的大小,再計算得到進度。
- 從FTPClient中可以知道:在上傳時:listener.transferred(l);l表示這次傳輸的量,但這似乎不是我們想要的,
- 修改爲:listener.transferred(done);這個done表示的是上傳的總量,是已經存在的,直接使用就好了。
- }
- 然後就可以通過重載方法加入這個監聽器client.download("remoteFile.ext", new java.io.File("localFile.ext"), new MyTransferListener());,其它略了。
- 對同一個FTPClient,多個線程間的操作是有影響的,如可以在其它線程中調用abortCurrentDataTransfer()來結當前的傳輸行爲。
- 這個方法傳入 false表示突然停止,傳入true表示發送ABOR命令,是個合法的結束。然後會有FTPAbortedException異常。
- ftp4j還支持斷點:
- client.download("remoteFile.ext", new java.io.File("localFile.ext"), 1056);表示從1057開始,前面的不需要再傳輸了。
- 上傳也類似 。
- 主動與被動的傳輸:
- 主動的傳輸行爲:
- 客戶端發送ip地址與端口號到服務器
- 客戶端請求服務器傳輸數據,開始監聽端口
- 服務器連接地址與端口
- 數據傳輸由一個新的通道開始傳輸。
- 主動的需要客戶端支持接收信息如果客戶端有防火牆,代理等,會有些問題,
- 被動的傳輸行爲:
- 客戶端請求服務器準備被動的數據傳輸。
- 服務器回覆並帶有ip與端口。
- 客戶端請求傳輸也連接。
- 數據傳輸由一個新的通道開始傳輸。
- 通過以下方式改變:
- client.setPassive(false); // Active mode
- client.setPassive(true); // Passive mode
- 默認是被動的。
- 這些屬性可以通過系統屬性來設置 :
- 如ftp4j.activeDataTransfer.acceptTimeout設置超時時間:
- java -Dftp4j.activeDataTransfer.hostAddress=178.12.34.167
- -Dftp4j.activeDataTransfer.portRange=6000-7000
- -Dftp4j.activeDataTransfer.acceptTimeout=5000 MyClass
- Set property values directly in the code. I.e.:
- System.setProperty("ftp4j.activeDataTransfer.hostAddress", "178.12.34.167");
- System.setProperty("ftp4j.activeDataTransfer.portRange", "6000-7000");
- System.setProperty("ftp4j.activeDataTransfer.acceptTimeout", "5000");
- 二進制與文本傳輸類型:
- 從源碼可以看出是以後綴名來判斷文件的類型,所以個人認爲,上傳的文件需要自己知道什麼類型的,不小心將二進制文件改爲txt後綴,可能會有些問題。
- client.setType(FTPClient.TYPE_TEXTUAL);
- client.setType(FTPClient.TYPE_BINARY);
- client.setType(FTPClient.TYPE_AUTO);
- 當然它提供了一些自定義的類型client.setTextualExtensionRecognizer(myRecognizer);
- 一些服務器支持數據壓縮傳輸,叫MODE Z。可以通過client.setCompressionEnabled(true);打開,在這之前可以確認:boolean compressionEnabled = client.isCompressionEnabled();
- 站點規範與命令:
- FTPReply reply = client.sendSiteCommand("YOUR COMMAND");
- 也可以自定義命令
- FTPReply reply = client.sendCustomCommand("YOUR COMMAND");
- 都返回一個FTPReply對象。可以從這個對象得到一些返回代碼,信息等內容。
- -----------------------------------------------
- 上面是ftp4j的文檔的一些知識。有了以上知識,開發一個android客戶端就相對容易多了。
- 如我想得到服務器的文件目錄操作(選擇文件,選擇目錄,進入目錄)
- 就可以使用ListView+ListAdapter顯示目錄與文件,然後由於 android的操作可以使用OnItemLongClickListener長按與短按OnItemClickListener分別指定一些操作,如短按可以選擇爲進入目錄:
- public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
- FTPFile ftpFile=mFileList.get(i);
- String filename=ftpFile.getName();
- if ("..".equals(filename)) {
- Log.d(TAG, "change directory up.");
- changeDirectoryUp();
- } else if (".".equals(filename)) {
- Log.d(TAG, "change directory root");
- changeDirectory("/");
- } else {
- if (ftpFile.getType()==FTPFile.TYPE_DIRECTORY) {
- Log.d(TAG, "change directory:"+filename);
- changeDirectory(filename);
- }
- }
- }
- mFtpClient.changeDirectory(path);
- mFtpClient.changeDirectoryUp();就是上面最終調用的方法。
- 然後在長按中:
- FTPFile ftpFile=mFileList.get(i);
- String filename=ftpFile.getName();
- if ("..".equals(filename)||".".equals(filename)) {
- Log.d(TAG, "在這裏沒有處理");
- } else {
- if (ftpFile.getType()==FTPFile.TYPE_DIRECTORY) {
- Log.d(TAG, "change directory:"+filename);
- selectDirectory(filename);
- }
- }
- selectDirectory()方法就是作爲選中目錄上傳目的地。然後可以將本地文件傳入這個目錄。
- 在改變目錄後調用:
- private void refreshFiles(FTPClient mFtpClient) throws IOException, FTPIllegalReplyException, FTPException {
- FTPFile[] files=new FTPFile[0];
- try {
- files=mFtpClient.list();
- List<FTPFile> ftpFiles=(List<FTPFile>) Arrays.asList(files);
- mFileList.clear();
- mFileList.addAll(ftpFiles);
- Message message=Message.obtain(mHandler, REFRESH_FILE);
- message.obj=mFtpClient.currentDirectory();
- mHandler.sendMessage(message);
- //這裏就是刷新ListView。
- } catch (FTPDataTransferException e) {
- e.printStackTrace();
- } catch (FTPAbortedException e) {
- e.printStackTrace();
- } catch (FTPListParseException e) {
- e.printStackTrace();
- }
- }
- 提供了上傳下載的功能後,就可以使用它了,建立一個簡單的ftp服務器,HOMEftpserver就是個不錯的東西,然後拍照或錄像再上傳。其它就不說了,直接傳代碼上來。完成的程序可以使用,只是有些簡陋,僅供參考。目前的需求就是拍照來錄像後上傳到ftp。