java實現FTP多線程斷點續傳,上傳下載!

package com.ftp;java

import java.io.File;  
import java.io.FileOutputStream;  
import java.io.IOException;  
import java.io.InputStream;  
import java.io.OutputStream;  
import java.io.PrintWriter;  
import java.io.RandomAccessFile;  
 
 
import org.apache.commons.net.PrintCommandListener;  
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;  
import org.junit.Test;
/** *//** 
 * 支持斷點續傳的FTP實用類  
 * @version 0.1 實現基本斷點上傳下載 
 * @version 0.2 實現上傳下載進度彙報 
 * @version 0.3 實現中文目錄建立及中文文件建立,添加對於中文的支持 
 */ 
public class ContinueFTP2  implements Runnable{  
 
 //枚舉類UploadStatus代碼 apache

 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;   //刪除遠程文件失敗
 }服務器

 //枚舉類DownloadStatus代碼
 public enum DownloadStatus {
 Remote_File_Noexist, //遠程文件不存在
 Local_Bigger_Remote, //本地文件大於遠程文件
 Download_From_Break_Success, //斷點下載文件成功
 Download_From_Break_Failed,   //斷點下載文件失敗
 Download_New_Success,    //全新下載文件成功
 Download_New_Failed;    //全新下載文件失敗
 }
 
    public FTPClient ftpClient = new FTPClient();  
    private String ftpURL,username,pwd,ftpport,file1,file2;   
    public ContinueFTP2(String _ftpURL,String _username,String _pwd,String _ftpport,String _file1,String _file2 ){  
        //設置將過程當中使用到的命令輸出到控制檯  
     ftpURL = _ftpURL;
     username = _username;
     pwd = _pwd;
     ftpport = _ftpport;
     file1 = _file1;
     file2 = _file2;
        this.ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));  
    }  
      
    /** *//** 
     * 鏈接到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(FTP.BINARY_FILE_TYPE);  
        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或是 http://www.guihua.org /subdirectory/file.ext 按照Linux上的路徑指定方式,支持多級目錄嵌套,支持遞歸建立不存在的目錄結構 
     * @return 上傳結果 
     * @throws IOException 
     */ 
    public UploadStatus upload(String local,String remote) throws IOException{  
        //設置PassiveMode傳輸  
        ftpClient.enterLocalPassiveMode();  
        //設置以二進制流的方式傳輸  
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);  
        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;  
    }  
      
   
    @Test
  
 public void run() {
  // TODO Auto-generated method stub
   
         try {  
          this.connect(ftpURL, new java.lang.Integer(ftpport), username, pwd);
//           myFtp.ftpClient.makeDirectory(new String(" 電視劇".getBytes("GBK"),"iso-8859-1"));  
//           myFtp.ftpClient.changeWorkingDirectory(new String(" 電視劇".getBytes("GBK"),"iso-8859-1"));  
//           myFtp.ftpClient.makeDirectory(new String(" 走西口".getBytes("GBK"),"iso-8859-1"));  
//           System.out.println(myFtp.upload("http://www.5a520.cn /yw.flv", "/yw.flv",5));  
//           System.out.println(myFtp.upload("http://www.5a520.cn /走西口24.mp4","/央視走西口/新浪網/走西口 24.mp4"));  
          //   System.out.println(myFtp.download("/ 央視走西口/新浪網/走西口24.mp4", "E:\\走西口242.mp4"));
         
           this.download(file1, file2);
         //  System.out.println(myFtp.upload("c:\\a.iso", "/a.iso"));
             this.disconnect();  
         } catch (IOException e) {  
             System.out.println("鏈接FTP出錯:"+e.getMessage());  
         }  
 }  
app

相關文章
相關標籤/搜索