需求:最新項目需要,寫個小功能,需求就是實時下載ftp指定文件夾下的所有文件(包括子目錄)到本地文件夾中,保留文件到目錄路徑不變。
分析:關鍵在於實時和下載並保持原目錄。實時使用線程的定時調度完成,主要做后者,這顯然要使用遞歸,但是ftp上的文件是不能直接得到相對路徑的(恕我才疏學淺,並沒有在FTPClient類中找到類似getPath()的方法),因此路徑是要自己記錄。總體思路有以下:
1、得到所有路徑以及子路徑:遞歸遍歷所有文件到路徑。參數:ftp為FTPClient對象,path為當前的路徑,pathArray保存當前的路徑,並將此路徑集合帶到主函數中去
getPath(ftp,path,pathArray);
public static void getPath(FTPClient ftp,String path,ArrayList<String> pathArray) throws IOException{ FTPFile[] files = ftp.listFiles(); for (FTPFile ftpFile : files) { if(ftpFile.getName().equals(".")||ftpFile.getName().equals(".."))continue; if(ftpFile.isDirectory()){//如果是目錄,則遞歸調用,查找里面所有文件 path+="/"+ftpFile.getName(); pathArray.add(path); ftp.changeWorkingDirectory(path);//改變當前路徑 getPath(ftp,path,pathArray);//遞歸調用 path=path.substring(0, path.lastIndexOf("/"));//避免對之后的同目錄下的路徑構造作出干擾, } } }
2、下載到指定的本地文件夾中,
download(ftp, pathArray, "c:\\download");程序之前出了寫錯誤,為了排查,我把下載分成兩部分,第一部分先將所有目錄創建完成,在第二個for循環中進行文件的下載。參數:ftp為FTPClient,pathArray為1中帶出的路徑集合,后面一個String為本地路徑
public static void download(FTPClient ftp,ArrayList<String> pathArray,String localRootPath) throws IOException{ for (String string : pathArray) { String localPath=localRootPath+string; File localFile = new File(localPath); if (!localFile.exists()) { localFile.mkdirs(); } } for (String string : pathArray) { String localPath=localRootPath+string;//構造本地路徑 ftp.changeWorkingDirectory(string); FTPFile[] file=ftp.listFiles(); for (FTPFile ftpFile : file) { if(ftpFile.getName().equals(".")||ftpFile.getName().equals(".."))continue; File localFile = new File(localPath); if(!ftpFile.isDirectory()){ OutputStream is = new FileOutputStream(localFile+"/"+ftpFile.getName()); ftp.retrieveFile(ftpFile.getName(), is); is.close(); } } } }
測試的主函數,使用的ftpClient為org.apache.commons.net.ftp.FTPClient:
public static void main(String[] args) throws SocketException, IOException { FTPClient ftp = new FTPClient(); ftp.connect("127.0.0.1"); ftp.login("test","test"); int reply; reply = ftp.getReplyCode(); if(!FTPReply.isPositiveCompletion(reply)) { ftp.disconnect(); System.err.println("FTP server refused connection."); System.exit(1); } ftp.setBufferSize(1024); ftp.setFileType(FTP.BINARY_FILE_TYPE); ftp.enterLocalPassiveMode(); String path=""; ArrayList<String> pathArray=new ArrayList<String>(); getPath(ftp,path,pathArray); System.out.println(pathArray); download(ftp, pathArray, "c:\\download"); ftp.logout(); ftp.disconnect(); }