1. 程式人生 > >JAVA FTPClient——遠端檔案操作

JAVA FTPClient——遠端檔案操作

Preface:最近忙的一個query理解服務的專案,關於分詞工具的問題,升級為使用北京側的分詞工具,屬於工程性質的。其中,需要載入動態庫和model資料夾,而且,由於服務部署到多臺機器上,為此,動態庫和model資料夾不能直接放到程式碼上帶過去,而是放到FTP機器上,當服務部署到多個機器或者機器擴容的時候,避免手工操作檔案,而是在服務啟動的時候,通過java FTPClient自動把檔案拉到服務所在的機器,然後在程式碼裡面載入動態庫和Model,拿到分詞控制代碼。每來了一個請求,通過該分詞控制代碼對這個請求裡面的query進行分詞。

一、FTPClient所需包

基本上使用apache的jar包,在程式碼中import即可

import org.apache.commons.net.ftp.FTPClient;

import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

說明:

FTPClient:用於連線機器

FTPFile:用於解析FTP機器上資料夾中的檔案

FTPReply:用於判斷是否連線成功

二、FTP連線

    FTPClient ftpClient = new FTPClient();
    try {
                //連線FTP
                ftpClient.connect(ftpHost, ftpPort);
            } catch (SocketException e) {
                e.printStackTrace();
                LOGGER.info("FTP的IP地址可能錯誤,請正確配置。");
            } catch (IOException e) {
                e.printStackTrace();
                LOGGER.info("hose port可能有問題");
            }

            try {
                ftpClient.login(username, password);
            } catch (IOException e) {
                e.printStackTrace();
                LOGGER.info("FTP賬號密碼可能有問題");
            }

            if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
                LOGGER.info("未連線到FTP,使用者名稱或密碼錯誤");
            } else {
                LOGGER.info("FTP連線成功");
            }
邏輯流程:

是否需要連線FTP:判斷動態庫和model資料夾在機器上,則需要連線FTP

連線FTP:主機名、埠號、賬號、密碼(滷煮用FTP機器的ip代替主機名,使用了主機名反而不行)

是否連線成功:FTPReply

注意:埠號為FTP埠號,非機器埠號(可能不同,多試下)

三、FTPClient傳輸

程式碼

try{
            ftpClient.changeWorkingDirectory(remotePath);
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);//傳輸的時候以二進位制傳輸,一定要加這行,不然(檔案變小)天大的坑!!!
            FTPFile[] fs = ftpClient.listFiles();
            for(FTPFile ff : fs){
                File localFile = new File(localPath + ff.getName());
                if(ff.isDirectory()){
                    //將路徑改到子資料夾,對子資料夾進行下載
                    ftpClient.changeWorkingDirectory(remotePath+ff.getName());
                    FTPFile[] fsubs = ftpClient.listFiles();
                    for(FTPFile fsubf : fsubs){
                        //建立子資料夾
                        File localSublDir = new File(localPath + ff.getName());
                        if(!localSublDir.exists()){
                            localSublDir.mkdir();
                        }

                        //獲取子資料夾裡面的子檔案的名字
                        File localSubFile = new File(localPath + ff.getName() +"/"+ fsubf.getName());
                        OutputStream is = new FileOutputStream(localSubFile);
                        ftpClient.retrieveFile(fsubf.getName(), is);
                        is.close();
                    }
                    ftpClient.changeWorkingDirectory(remotePath);
                }else{
                    OutputStream is = new FileOutputStream(localFile);
                    ftpClient.retrieveFile(ff.getName(), is);
                    is.close();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

說明

changeWorkingDirectory():定位到FTP機器上資料夾的位置

setFileType():設定FTP傳輸型別。最好使用二進位制傳輸,另外還有傳輸編碼格式(utf-8)設定等,不設定的話,傳輸後的檔案可能有所變化,使用不了了,天大的坑!!!

listFiles():將資料夾裡面的檔案遍歷出來

localFile:本地File名

is:將File轉為檔案流

retrieveFile():將這個檔案寫到這個檔案流中

注:

由於滷煮的資料夾裡還有資料夾,兩層,為此,需要進入子資料夾進行傳輸,不然的話,子資料夾裡的檔案傳輸不過去;當資料夾多層的時候,需要遞迴傳輸。

有的時候,可能涉及許可權問題。從FTP機器上的某個路徑傳到另外一個機器只讀的路徑下,setReadable、setWritable倆函式似乎根本沒用。咋整的話,只能mkdir(),然後讀到建立的路徑下比較好。