org.apache.commons.net.ftp包開發FTP客戶端,實現斷點續傳,中文支持

利用org.apache.commons.net.ftp包實現一個簡單的ftp客戶端實用類。主要實現一下功能 java

1.支持上傳下載。支持斷點續傳 apache

2.支持進度彙報 服務器

3.支持對於中文目錄及中文文件建立的支持。 app

具體請看代碼,上面有詳細的註釋。簡化版本請參見http://zhouzaibao.iteye.com/blog/342766 dom

枚舉類UploadStatus代碼 this

Java代碼   收藏代碼
  1. public enum UploadStatus {  
  2.     Create_Directory_Fail,      //遠程服務器相應目錄建立失敗  
  3.     Create_Directory_Success,   //遠程服務器闖將目錄成功  
  4.     Upload_New_File_Success,    //上傳新文件成功  
  5.     Upload_New_File_Failed,     //上傳新文件失敗  
  6.     File_Exits,                 //文件已經存在  
  7.     Remote_Bigger_Local,        //遠程文件大於本地文件  
  8.     Upload_From_Break_Success,  //斷點續傳成功  
  9.     Upload_From_Break_Failed,   //斷點續傳失敗  
  10.     Delete_Remote_Faild;        //刪除遠程文件失敗  
  11. }  

枚舉類DownloadStatus代碼 spa

Java代碼   收藏代碼
  1. public enum DownloadStatus {  
  2.     Remote_File_Noexist,    //遠程文件不存在  
  3.     Local_Bigger_Remote,    //本地文件大於遠程文件  
  4.     Download_From_Break_Success,    //斷點下載文件成功  
  5.     Download_From_Break_Failed,     //斷點下載文件失敗  
  6.     Download_New_Success,           //全新下載文件成功  
  7.     Download_New_Failed;            //全新下載文件失敗  
  8. }  
 

核心FTP代碼 .net

Java代碼   收藏代碼
  1. import java.io.File;  
  2. import java.io.FileOutputStream;  
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5. import java.io.OutputStream;  
  6. import java.io.PrintWriter;  
  7. import java.io.RandomAccessFile;  
  8.   
  9. import open.mis.data.DownloadStatus;  
  10. import open.mis.data.UploadStatus;  
  11.   
  12. import org.apache.commons.net.PrintCommandListener;  
  13. import org.apache.commons.net.ftp.FTP;  
  14. import org.apache.commons.net.ftp.FTPClient;  
  15. import org.apache.commons.net.ftp.FTPFile;  
  16. import org.apache.commons.net.ftp.FTPReply;  
  17.   
  18. /** 
  19.  * 支持斷點續傳的FTP實用類 
  20.  * @author BenZhou 
  21.  * @version 0.1 實現基本斷點上傳下載 
  22.  * @version 0.2 實現上傳下載進度彙報 
  23.  * @version 0.3 實現中文目錄建立及中文文件建立,添加對於中文的支持 
  24.  */  
  25. public class ContinueFTP {  
  26.     public FTPClient ftpClient = new FTPClient();  
  27.       
  28.     public ContinueFTP(){  
  29.         //設置將過程當中使用到的命令輸出到控制檯  
  30.         this.ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));  
  31.     }  
  32.       
  33.     /** 
  34.      * 鏈接到FTP服務器 
  35.      * @param hostname 主機名 
  36.      * @param port 端口 
  37.      * @param username 用戶名 
  38.      * @param password 密碼 
  39.      * @return 是否鏈接成功 
  40.      * @throws IOException 
  41.      */  
  42.     public boolean connect(String hostname,int port,String username,String password) throws IOException{  
  43.         ftpClient.connect(hostname, port);  
  44.         ftpClient.setControlEncoding("GBK");  
  45.         if(FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){  
  46.             if(ftpClient.login(username, password)){  
  47.                 return true;  
  48.             }  
  49.         }  
  50.         disconnect();  
  51.         return false;  
  52.     }  
  53.       
  54.     /** 
  55.      * 從FTP服務器上下載文件,支持斷點續傳,上傳百分比彙報 
  56.      * @param remote 遠程文件路徑 
  57.      * @param local 本地文件路徑 
  58.      * @return 上傳的狀態 
  59.      * @throws IOException 
  60.      */  
  61.     public DownloadStatus download(String remote,String local) throws IOException{  
  62.         //設置被動模式  
  63.         ftpClient.enterLocalPassiveMode();  
  64.         //設置以二進制方式傳輸  
  65.         ftpClient.setFileType(FTP.BINARY_FILE_TYPE);  
  66.         DownloadStatus result;  
  67.           
  68.         //檢查遠程文件是否存在  
  69.         FTPFile[] files = ftpClient.listFiles(new String(remote.getBytes("GBK"),"iso-8859-1"));  
  70.         if(files.length != 1){  
  71.             System.out.println("遠程文件不存在");  
  72.             return DownloadStatus.Remote_File_Noexist;  
  73.         }  
  74.           
  75.         long lRemoteSize = files[0].getSize();  
  76.         File f = new File(local);  
  77.         //本地存在文件,進行斷點下載  
  78.         if(f.exists()){  
  79.             long localSize = f.length();  
  80.             //判斷本地文件大小是否大於遠程文件大小  
  81.             if(localSize >= lRemoteSize){  
  82.                 System.out.println("本地文件大於遠程文件,下載停止");  
  83.                 return DownloadStatus.Local_Bigger_Remote;  
  84.             }  
  85.               
  86.             //進行斷點續傳,並記錄狀態  
  87.             FileOutputStream out = new FileOutputStream(f,true);  
  88.             ftpClient.setRestartOffset(localSize);  
  89.             InputStream in = ftpClient.retrieveFileStream(new String(remote.getBytes("GBK"),"iso-8859-1"));  
  90.             byte[] bytes = new byte[1024];  
  91.             long step = lRemoteSize /100;  
  92.             long process=localSize /step;  
  93.             int c;  
  94.             while((c = in.read(bytes))!= -1){  
  95.                 out.write(bytes,0,c);  
  96.                 localSize+=c;  
  97.                 long nowProcess = localSize /step;  
  98.                 if(nowProcess > process){  
  99.                     process = nowProcess;  
  100.                     if(process % 10 == 0)  
  101.                         System.out.println("下載進度:"+process);  
  102.                     //TODO 更新文件下載進度,值存放在process變量中  
  103.                 }  
  104.             }  
  105.             in.close();  
  106.             out.close();  
  107.             boolean isDo = ftpClient.completePendingCommand();  
  108.             if(isDo){  
  109.                 result = DownloadStatus.Download_From_Break_Success;  
  110.             }else {  
  111.                 result = DownloadStatus.Download_From_Break_Failed;  
  112.             }  
  113.         }else {  
  114.             OutputStream out = new FileOutputStream(f);  
  115.             InputStream in= ftpClient.retrieveFileStream(new String(remote.getBytes("GBK"),"iso-8859-1"));  
  116.             byte[] bytes = new byte[1024];  
  117.             long step = lRemoteSize /100;  
  118.             long process=0;  
  119.             long localSize = 0L;  
  120.             int c;  
  121.             while((c = in.read(bytes))!= -1){  
  122.                 out.write(bytes, 0, c);  
  123.                 localSize+=c;  
  124.                 long nowProcess = localSize /step;  
  125.                 if(nowProcess > process){  
  126.                     process = nowProcess;  
  127.                     if(process % 10 == 0)  
  128.                         System.out.println("下載進度:"+process);  
  129.                     //TODO 更新文件下載進度,值存放在process變量中  
  130.                 }  
  131.             }  
  132.             in.close();  
  133.             out.close();  
  134.             boolean upNewStatus = ftpClient.completePendingCommand();  
  135.             if(upNewStatus){  
  136.                 result = DownloadStatus.Download_New_Success;  
  137.             }else {  
  138.                 result = DownloadStatus.Download_New_Failed;  
  139.             }  
  140.         }  
  141.         return result;  
  142.     }  
  143.       
  144.     /** 
  145.      * 上傳文件到FTP服務器,支持斷點續傳 
  146.      * @param local 本地文件名稱,絕對路徑 
  147.      * @param remote 遠程文件路徑,使用/home/directory1/subdirectory/file.ext 按照Linux上的路徑指定方式,支持多級目錄嵌套,支持遞歸建立不存在的目錄結構 
  148.      * @return 上傳結果 
  149.      * @throws IOException 
  150.      */  
  151.     public UploadStatus upload(String local,String remote) throws IOException{  
  152.         //設置PassiveMode傳輸  
  153.         ftpClient.enterLocalPassiveMode();  
  154.         //設置以二進制流的方式傳輸  
  155.         ftpClient.setFileType(FTP.BINARY_FILE_TYPE);  
  156.         ftpClient.setControlEncoding("GBK");  
  157.         UploadStatus result;  
  158.         //對遠程目錄的處理  
  159.         String remoteFileName = remote;  
  160.         if(remote.contains("/")){  
  161.             remoteFileName = remote.substring(remote.lastIndexOf("/")+1);  
  162.             //建立服務器遠程目錄結構,建立失敗直接返回  
  163.             if(CreateDirecroty(remote, ftpClient)==UploadStatus.Create_Directory_Fail){  
  164.                 return UploadStatus.Create_Directory_Fail;  
  165.             }  
  166.         }  
  167.           
  168.         //檢查遠程是否存在文件  
  169.         FTPFile[] files = ftpClient.listFiles(new String(remoteFileName.getBytes("GBK"),"iso-8859-1"));  
  170.         if(files.length == 1){  
  171.             long remoteSize = files[0].getSize();  
  172.             File f = new File(local);  
  173.             long localSize = f.length();  
  174.             if(remoteSize==localSize){  
  175.                 return UploadStatus.File_Exits;  
  176.             }else if(remoteSize > localSize){  
  177.                 return UploadStatus.Remote_Bigger_Local;  
  178.             }  
  179.               
  180.             //嘗試移動文件內讀取指針,實現斷點續傳  
  181.             result = uploadFile(remoteFileName, f, ftpClient, remoteSize);  
  182.               
  183.             //若是斷點續傳沒有成功,則刪除服務器上文件,從新上傳  
  184.             if(result == UploadStatus.Upload_From_Break_Failed){  
  185.                 if(!ftpClient.deleteFile(remoteFileName)){  
  186.                     return UploadStatus.Delete_Remote_Faild;  
  187.                 }  
  188.                 result = uploadFile(remoteFileName, f, ftpClient, 0);  
  189.             }  
  190.         }else {  
  191.             result = uploadFile(remoteFileName, new File(local), ftpClient, 0);  
  192.         }  
  193.         return result;  
  194.     }  
  195.     /** 
  196.      * 斷開與遠程服務器的鏈接 
  197.      * @throws IOException 
  198.      */  
  199.     public void disconnect() throws IOException{  
  200.         if(ftpClient.isConnected()){  
  201.             ftpClient.disconnect();  
  202.         }  
  203.     }  
  204.       
  205.     /** 
  206.      * 遞歸建立遠程服務器目錄 
  207.      * @param remote 遠程服務器文件絕對路徑 
  208.      * @param ftpClient FTPClient對象 
  209.      * @return 目錄建立是否成功 
  210.      * @throws IOException 
  211.      */  
  212.     public UploadStatus CreateDirecroty(String remote,FTPClient ftpClient) throws IOException{  
  213.         UploadStatus status = UploadStatus.Create_Directory_Success;  
  214.         String directory = remote.substring(0,remote.lastIndexOf("/")+1);  
  215.         if(!directory.equalsIgnoreCase("/")&&!ftpClient.changeWorkingDirectory(new String(directory.getBytes("GBK"),"iso-8859-1"))){  
  216.             //若是遠程目錄不存在,則遞歸建立遠程服務器目錄  
  217.             int start=0;  
  218.             int end = 0;  
  219.             if(directory.startsWith("/")){  
  220.                 start = 1;  
  221.             }else{  
  222.                 start = 0;  
  223.             }  
  224.             end = directory.indexOf("/",start);  
  225.             while(true){  
  226.                 String subDirectory = new String(remote.substring(start,end).getBytes("GBK"),"iso-8859-1");  
  227.                 if(!ftpClient.changeWorkingDirectory(subDirectory)){  
  228.                     if(ftpClient.makeDirectory(subDirectory)){  
  229.                         ftpClient.changeWorkingDirectory(subDirectory);  
  230.                     }else {  
  231.                         System.out.println("建立目錄失敗");  
  232.                         return UploadStatus.Create_Directory_Fail;  
  233.                     }  
  234.                 }  
  235.                   
  236.                 start = end + 1;  
  237.                 end = directory.indexOf("/",start);  
  238.                   
  239.                 //檢查全部目錄是否建立完畢  
  240.                 if(end <= start){  
  241.                     break;  
  242.                 }  
  243.             }  
  244.         }  
  245.         return status;  
  246.     }  
  247.       
  248.     /** 
  249.      * 上傳文件到服務器,新上傳和斷點續傳 
  250.      * @param remoteFile 遠程文件名,在上傳以前已經將服務器工做目錄作了改變 
  251.      * @param localFile 本地文件File句柄,絕對路徑 
  252.      * @param processStep 須要顯示的處理進度步進值 
  253.      * @param ftpClient FTPClient引用 
  254.      * @return  
  255.      * @throws IOException 
  256.      */  
  257.     public UploadStatus uploadFile(String remoteFile,File localFile,FTPClient ftpClient,long remoteSize) throws IOException{  
  258.         UploadStatus status;  
  259.         //顯示進度的上傳  
  260.         long step = localFile.length() / 100;  
  261.         long process = 0;  
  262.         long localreadbytes = 0L;  
  263.         RandomAccessFile raf = new RandomAccessFile(localFile,"r");  
  264.         OutputStream out = ftpClient.appendFileStream(new String(remoteFile.getBytes("GBK"),"iso-8859-1"));  
  265.         //斷點續傳  
  266.         if(remoteSize>0){  
  267.             ftpClient.setRestartOffset(remoteSize);  
  268.             process = remoteSize /step;  
  269.             raf.seek(remoteSize);  
  270.             localreadbytes = remoteSize;  
  271.         }  
  272.         byte[] bytes = new byte[1024];  
  273.         int c;  
  274.         while((c = raf.read(bytes))!= -1){  
  275.             out.write(bytes,0,c);  
  276.             localreadbytes+=c;  
  277.             if(localreadbytes / step != process){  
  278.                 process = localreadbytes / step;  
  279.                 System.out.println("上傳進度:" + process);  
  280.                 //TODO 彙報上傳狀態  
  281.             }  
  282.         }  
  283.         out.flush();  
  284.         raf.close();  
  285.         out.close();  
  286.         boolean result =ftpClient.completePendingCommand();  
  287.         if(remoteSize > 0){  
  288.             status = result?UploadStatus.Upload_From_Break_Success:UploadStatus.Upload_From_Break_Failed;  
  289.         }else {  
  290.             status = result?UploadStatus.Upload_New_File_Success:UploadStatus.Upload_New_File_Failed;  
  291.         }  
  292.         return status;  
  293.     }  
  294.       
  295.     public static void main(String[] args) {  
  296.         ContinueFTP myFtp = new ContinueFTP();  
  297.         try {  
  298.             myFtp.connect("192.168.21.181"21"nid""123");  
  299. //          myFtp.ftpClient.makeDirectory(new String("電視劇".getBytes("GBK"),"iso-8859-1"));  
  300. //          myFtp.ftpClient.changeWorkingDirectory(new String("電視劇".getBytes("GBK"),"iso-8859-1"));  
  301. //          myFtp.ftpClient.makeDirectory(new String("走西口".getBytes("GBK"),"iso-8859-1"));  
  302. //          System.out.println(myFtp.upload("E:\\yw.flv", "/yw.flv",5));  
  303. //          System.out.println(myFtp.upload("E:\\走西口24.mp4","/央視走西口/新浪網/走西口24.mp4"));  
  304.             System.out.println(myFtp.download("/央視走西口/新浪網/走西口24.mp4""E:\\走西口242.mp4"));  
  305.             myFtp.disconnect();  
  306.         } catch (IOException e) {  
  307.             System.out.println("鏈接FTP出錯:"+e.getMessage());  
  308.         }  
  309.     }  
  310. }  
相關文章
相關標籤/搜索