ftp文件長傳4

使用Apache的FtpClient做FTP上傳下載  

2010-05-17 19:13:50|  分類: java |字號 訂閱

引自:http://hi.baidu.com/victorlin23/blog/item/edc62a35dbae8a1a91ef3947.html

/*
要用到的jar:
1.commons-io-1.4.jar
2.commons-net-1.4.1.jar
3.commons-pool-1.3.jar
4.jakarta-oro-2.0.8.jar
*/

import java.io.File;
import java.io.IOException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
public class FtpHelper {
private FTPClient ftpClient = new FTPClient();   
/** 
      * 連接到FTP服務器 
      * @param hostname 主機名 
      * @param port 端口 
      * @param username 用戶名 
      * @param password 密碼 
      * @return 是否連接成功 
      * @throws IOException 
      */ 
     public boolean connect(String hostname,int port,String username,String password) throws IOException{   
         ftpClient.connect(hostname, port);   
         ftpClient.setControlEncoding("GBK");   
         if(FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){   
             if(ftpClient.login(username, password)){   
                 return true;   
             }   
         }   
         disconnect();   
         return false;   
     }   
        
     /** 
      * 從FTP服務器上下載文件,支持斷點續傳,上傳百分比彙報 
      * @param remote 遠程文件路徑,/代表根目錄
      * @param local 本地文件路徑 
      * @return 上傳的狀態 
      * @throws IOException 
      */ 
     public DownloadStatus download(String remote,String local) throws IOException{   
         //設置被動模式   
         ftpClient.enterLocalPassiveMode();   
         //設置以二進制方式傳輸   
         ftpClient.setFileType([url=ftp://ftp.BINARY_FILE_TYPE]FTP.BINARY_FILE_TYPE[/url]);   
         DownloadStatus result;      
         //檢查遠程文件是否存在   
         FTPFile[] files = ftpClient.listFiles(new String(remote.getBytes("GBK"),"iso-8859-1"));   
         if(files.length != 1){   
             System.out.println("遠程文件不存在");   
             return DownloadStatus.Remote_File_Noexist;   
         }   
         long lRemoteSize = files[0].getSize();   
         File f = new File(local);   
         //本地存在文件,進行斷點下載   
         if(f.exists()){   
             long localSize = f.length();   
             //判斷本地文件大小是否大於遠程文件大小   
             if(localSize >= lRemoteSize){   
                 System.out.println("本地文件大於遠程文件,下載中止");   
                 return DownloadStatus.Local_Bigger_Remote;   
             }   
                
             //進行斷點續傳,並記錄狀態   
             FileOutputStream out = new FileOutputStream(f,true);   
             ftpClient.setRestartOffset(localSize);   
             InputStream in = ftpClient.retrieveFileStream(new String(remote.getBytes("GBK"),"iso-8859-1"));   
             byte[] bytes = new byte[1024];   
             long step = lRemoteSize /100;   
             long process=localSize /step;   
             int c;   
             while((c = in.read(bytes))!= -1){   
                 out.write(bytes,0,c);   
                 localSize+=c;   
                 long nowProcess = localSize /step;   
                 if(nowProcess > process){   
                     process = nowProcess;   
                     if(process % 10 == 0)   
                         System.out.println("下載進度:"+process);   
                     //TODO 更新文件下載進度,值存放在process變量中   
                 }   
             }   
             in.close();   
             out.close();   
             boolean isDo = ftpClient.completePendingCommand();   
             if(isDo){   
                 result = DownloadStatus.Download_From_Break_Success;   
             }else {   
                 result = DownloadStatus.Download_From_Break_Failed;   
             }   
         }else {   
             OutputStream out = new FileOutputStream(f);   
             InputStream in= ftpClient.retrieveFileStream(new String(remote.getBytes("GBK"),"iso-8859-1"));   
             byte[] bytes = new byte[1024];   
             long step = lRemoteSize /100;   
             long process=0;   
             long localSize = 0L;   
             int c;   
             while((c = in.read(bytes))!= -1){   
                 out.write(bytes, 0, c);   
                 localSize+=c;   
                 long nowProcess = localSize /step;   
                 if(nowProcess > process){   
                     process = nowProcess;   
                     if(process % 10 == 0)   
                         System.out.println("下載進度:"+process);   
                     //TODO 更新文件下載進度,值存放在process變量中   
                 }   
             }   
             in.close();   
             out.close();   
             boolean upNewStatus = ftpClient.completePendingCommand();   
             if(upNewStatus){   
                 result = DownloadStatus.Download_New_Success;   
             }else {   
                 result = DownloadStatus.Download_New_Failed;   
             }   
         }   
         return result;   
     }   
        
     /** 
      * 上傳文件到FTP服務器,支持斷點續傳 
      * @param local 本地文件名稱,絕對路徑 
      * @param remote 遠程文件路徑,使用/home/directory1/subdirectory/file.ext 按照Linux上的路徑指定方式,支持多級目錄嵌套,支持遞歸創建不存在的目錄結構,/代表用戶根目錄
      * @return 上傳結果 
      * @throws IOException 
      */ 
     public UploadStatus upload(String local,String remote) throws IOException{   
         //設置PassiveMode傳輸   
         ftpClient.enterLocalPassiveMode();   
         //設置以二進制流的方式傳輸   
         ftpClient.setFileType([url=ftp://ftp.BINARY_FILE_TYPE]FTP.BINARY_FILE_TYPE[/url]);   
         ftpClient.setControlEncoding("GBK");   
         UploadStatus result;   
         //對遠程目錄的處理   
         String remoteFileName = remote;   
         if(remote.contains("/")){   
             remoteFileName = remote.substring(remote.lastIndexOf("/")+1);   
             //創建服務器遠程目錄結構,創建失敗直接返回   
             if(createDirecroty(remote, ftpClient)==UploadStatus.Create_Directory_Fail){   
                 return UploadStatus.Create_Directory_Fail;   
             }   
         }   
            
         //檢查遠程是否存在文件   
         FTPFile[] files = ftpClient.listFiles(new String(remoteFileName.getBytes("GBK"),"iso-8859-1"));   
         if(files.length == 1){   
             long remoteSize = files[0].getSize();   
             File f = new File(local);   
             long localSize = f.length();   
             if(remoteSize==localSize){   //文件存在
                 return UploadStatus.File_Exits;   
             }else if(remoteSize > localSize){   
                 return UploadStatus.Remote_Bigger_Local;   
             }   
                
             //嘗試移動文件內讀取指針,實現斷點續傳   
             result = uploadFile(remoteFileName, f, ftpClient, remoteSize);   
                
             //如果斷點續傳沒有成功,則刪除服務器上文件,重新上傳   
             if(result == UploadStatus.Upload_From_Break_Failed){   
                 if(!ftpClient.deleteFile(remoteFileName)){   
                     return UploadStatus.Delete_Remote_Faild;   
                 }   
                 result = uploadFile(remoteFileName, f, ftpClient, 0);   
             }   
         }else {   
             result = uploadFile(remoteFileName, new File(local), ftpClient, 0);   
         }   
         return result;   
     }   
     /** 
      * 斷開與遠程服務器的連接 
      * @throws IOException 
      */ 
     public void disconnect() throws IOException{   
         if(ftpClient.isConnected()){   
             ftpClient.disconnect();   
         }   
     }   
        
     /** 
      * 遞歸創建遠程服務器目錄 
      * @param remote 遠程服務器文件絕對路徑 
      * @param ftpClient FTPClient對象 
      * @return 目錄創建是否成功 
      * @throws IOException 
      */ 
     public UploadStatus createDirecroty(String remote,FTPClient ftpClient) throws IOException{   
         UploadStatus status = UploadStatus.Create_Directory_Success;   
         String directory = remote.substring(0,remote.lastIndexOf("/")+1);   
         if(!directory.equalsIgnoreCase("/")&&!ftpClient.changeWorkingDirectory(new String(directory.getBytes("GBK"),"iso-8859-1"))){   
             //如果遠程目錄不存在,則遞歸創建遠程服務器目錄   
             int start=0;   
             int end = 0;   
             if(directory.startsWith("/")){   
                 start = 1;   
             }else{   
                 start = 0;   
             }   
             end = directory.indexOf("/",start);   
             while(true){   
                 String subDirectory = new String(remote.substring(start,end).getBytes("GBK"),"iso-8859-1");   
                 if(!ftpClient.changeWorkingDirectory(subDirectory)){   
                     if(ftpClient.makeDirectory(subDirectory)){   
                         ftpClient.changeWorkingDirectory(subDirectory);   
                     }else {   
                         System.out.println("創建目錄失敗");   
                         return UploadStatus.Create_Directory_Fail;   
                     }   
                 }   
                    
                 start = end + 1;   
                 end = directory.indexOf("/",start);   
                    
                 //檢查所有目錄是否創建完畢   
                 if(end <= start){   
                     break;   
                 }   
             }   
         }   
         return status;   
     }   
        
     /** 
      * 上傳文件到服務器,新上傳和斷點續傳 
      * @param remoteFile 遠程文件名,在上傳之前已經將服務器工作目錄做了改變 
      * @param localFile 本地文件File句柄,絕對路徑 
      * @param processStep 需要顯示的處理進度步進值 
      * @param ftpClient FTPClient引用 
      * @return 
      * @throws IOException 
      */ 
     public UploadStatus uploadFile(String remoteFile,File localFile,FTPClient ftpClient,long remoteSize) throws IOException{   
         UploadStatus status;   
         //顯示進度的上傳   
         long step = localFile.length() / 100;   
         long process = 0;   
         long localreadbytes = 0L;   
         RandomAccessFile raf = new RandomAccessFile(localFile,"r");   
         OutputStream out = ftpClient.appendFileStream(new String(remoteFile.getBytes("GBK"),"iso-8859-1"));   
         //斷點續傳   
         if(remoteSize>0){   
             ftpClient.setRestartOffset(remoteSize);   
             process = remoteSize /step;   
             raf.seek(remoteSize);   
             localreadbytes = remoteSize;   
         }   
         byte[] bytes = new byte[1024];   
         int c;   
         while((c = raf.read(bytes))!= -1){   
             out.write(bytes,0,c);   
             localreadbytes+=c;   
             if(localreadbytes / step != process){   
                 process = localreadbytes / step;   
                 System.out.println("上傳進度:" + process);   
                 //TODO 彙報上傳狀態   
                 
                 
                 
             }   
         }   
         out.flush();   
         raf.close();   
         out.close();   
         boolean result =ftpClient.completePendingCommand();   
         if(remoteSize > 0){   
             status = result?UploadStatus.Upload_From_Break_Success:UploadStatus.Upload_From_Break_Failed;   
         }else {   
             status = result?UploadStatus.Upload_New_File_Success:UploadStatus.Upload_New_File_Failed;   
         }   
         return status;   
     }   
     
     public static void main(String[] args) {
      FtpHelper myFtp = new FtpHelper();   
         try {   
             myFtp.connect("192.168.187.130", 21, "root", "1-1=0");   
             System.out.println(myFtp.upload("2.txt","/2.txt"));  
             //System.out.println(myFtp.download("/index.html","index.html"));
             myFtp.disconnect();   
         } catch (IOException e) {   
          
             System.out.println("連接FTP出錯:"+e.getMessage());   
             e.printStackTrace();
         }  
}
   
    public enum UploadStatus {   
        Create_Directory_Fail,      //遠程服務器相應目錄創建失敗   
        Create_Directory_Success,   //遠程服務器闖將目錄成功   
        Upload_New_File_Success,    //上傳新文件成功   
        Upload_New_File_Failed,     //上傳新文件失敗   
        File_Exits,                 //文件已經存在   
        Remote_Bigger_Local,        //遠程文件大於本地文件   
        Upload_From_Break_Success, //斷點續傳成功   
        Upload_From_Break_Failed,   //斷點續傳失敗   
        Delete_Remote_Faild;        //刪除遠程文件失敗   
    }
    
    public enum DownloadStatus {   
     Remote_File_Noexist,        //遠程文件不存在   
        Download_New_Success,    //下載文件成功   
        Download_New_Failed,     //下載文件失敗    
        Local_Bigger_Remote,        //本地文件大於遠程文件
        Download_From_Break_Success, //斷點續傳成功   
        Download_From_Break_Failed;   //斷點續傳失敗   
    } 
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章