java实现FTP多线程断点续传,上传下载!

来源:互联网 发布:网络推广做什么的 编辑:程序博客网 时间:2024/06/10 07:56
 

java实现FTP多线程断点续传,上传下载!

 357人阅读 评论(0) 收藏 举报
 分类:

添加 apache.commons.NET.ftp 包

[java] view plain copy
  1. package com.ftp;   
  2.   
  3. import java.io.File;     
  4. import java.io.FileOutputStream;     
  5. import java.io.IOException;     
  6. import java.io.InputStream;     
  7. import java.io.OutputStream;     
  8. import java.io.PrintWriter;     
  9. import java.io.RandomAccessFile;     
  10.     
  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. import org.junit.Test;   
  18. /** *//**   
  19. * 支持断点续传的FTP实用类   
  20. * @version 0.1 实现基本断点上传下载   
  21. * @version 0.2 实现上传下载进度汇报   
  22. * @version 0.3 实现中文目录创建及中文文件创建,添加对于中文的支持   
  23. */    
  24. public class ContinueFTP2  implements Runnable{     
  25.   
  26. //枚举类UploadStatus代码   
  27.   
  28. public enum UploadStatus {   
  29. Create_Directory_Fail,   //远程服务器相应目录创建失败   
  30. Create_Directory_Success, //远程服务器闯将目录成功   
  31. Upload_New_File_Success, //上传新文件成功   
  32. Upload_New_File_Failed,   //上传新文件失败   
  33. File_Exits,      //文件已经存在   
  34. Remote_Bigger_Local,   //远程文件大于本地文件   
  35. Upload_From_Break_Success, //断点续传成功   
  36. Upload_From_Break_Failed, //断点续传失败   
  37. Delete_Remote_Faild;   //删除远程文件失败   
  38. }   
  39.   
  40. //枚举类DownloadStatus代码   
  41. public enum DownloadStatus {   
  42. Remote_File_Noexist, //远程文件不存在   
  43. Local_Bigger_Remote, //本地文件大于远程文件   
  44. Download_From_Break_Success, //断点下载文件成功   
  45. Download_From_Break_Failed,   //断点下载文件失败   
  46. Download_New_Success,    //全新下载文件成功   
  47. Download_New_Failed;    //全新下载文件失败   
  48. }   
  49.   
  50.     public FTPClient ftpClient = new FTPClient();     
  51.     private String ftpURL,username,pwd,ftpport,file1,file2;      
  52.     public ContinueFTP2(String _ftpURL,String _username,String _pwd,String _ftpport,String _file1,String _file2 ){     
  53.         //设置将过程中使用到的命令输出到控制台     
  54.      ftpURL = _ftpURL;   
  55.      username = _username;   
  56.      pwd = _pwd;   
  57.      ftpport = _ftpport;   
  58.      file1 = _file1;   
  59.      file2 = _file2;   
  60.         this.ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));     
  61.     }     
  62.          
  63.     /** *//**   
  64.      * 连接到FTP服务器   
  65.      * @param hostname 主机名   
  66.      * @param port 端口   
  67.      * @param username 用户名   
  68.      * @param password 密码   
  69.      * @return 是否连接成功   
  70.      * @throws IOException   
  71.      */    
  72.     public boolean connect(String hostname,int port,String username,String password) throws IOException{     
  73.         ftpClient.connect(hostname, port);     
  74.         ftpClient.setControlEncoding("GBK");     
  75.         if(FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){     
  76.             if(ftpClient.login(username, password)){     
  77.                 return true;     
  78.             }     
  79.         }     
  80.         disconnect();     
  81.         return false;     
  82.     }     
  83.          
  84.     /** *//**   
  85.      * 从FTP服务器上下载文件,支持断点续传,上传百分比汇报   
  86.      * @param remote 远程文件路径   
  87.      * @param local 本地文件路径   
  88.      * @return 上传的状态   
  89.      * @throws IOException   
  90.      */    
  91.     public DownloadStatus download(String remote,String local) throws IOException{     
  92.         //设置被动模式     
  93.         ftpClient.enterLocalPassiveMode();     
  94.         //设置以二进制方式传输     
  95.         ftpClient.setFileType(FTP.BINARY_FILE_TYPE);     
  96.         DownloadStatus result;     
  97.              
  98.         //检查远程文件是否存在     
  99.         FTPFile[] files = ftpClient.listFiles(new String(remote.getBytes("GBK"),"iso-8859-1"));     
  100.         if(files.length != 1){     
  101.             System.out.println("远程文件不存在");     
  102.             return DownloadStatus.Remote_File_Noexist;     
  103.         }     
  104.              
  105.         long lRemoteSize = files[0].getSize();     
  106.         File f = new File(local);     
  107.         //本地存在文件,进行断点下载     
  108.         if(f.exists()){     
  109.             long localSize = f.length();     
  110.             //判断本地文件大小是否大于远程文件大小     
  111.             if(localSize >= lRemoteSize){     
  112.                 System.out.println("本地文件大于远程文件,下载中止");     
  113.                 return DownloadStatus.Local_Bigger_Remote;     
  114.             }     
  115.                  
  116.             //进行断点续传,并记录状态     
  117.             FileOutputStream out = new FileOutputStream(f,true);     
  118.             ftpClient.setRestartOffset(localSize);     
  119.             InputStream in = ftpClient.retrieveFileStream(new String(remote.getBytes("GBK"),"iso-8859-1"));     
  120.             byte[] bytes = new byte[1024];     
  121.             long step = lRemoteSize /100;     
  122.             long process=localSize /step;     
  123.             int c;     
  124.             while((c = in.read(bytes))!= -1){     
  125.                 out.write(bytes,0,c);     
  126.                 localSize+=c;     
  127.                 long nowProcess = localSize /step;     
  128.                 if(nowProcess > process){     
  129.                     process = nowProcess;     
  130.                     if(process % 10 == 0)     
  131.                         System.out.println("下载进度:"+process);     
  132.                     //TODO 更新文件下载进度,值存放在process变量中     
  133.                 }     
  134.             }     
  135.             in.close();     
  136.             out.close();     
  137.             boolean isDo = ftpClient.completePendingCommand();     
  138.             if(isDo){     
  139.                 result = DownloadStatus.Download_From_Break_Success;     
  140.             }else {     
  141.                 result = DownloadStatus.Download_From_Break_Failed;     
  142.             }     
  143.         }else {     
  144.             OutputStream out = new FileOutputStream(f);     
  145.             InputStream in= ftpClient.retrieveFileStream(new String(remote.getBytes("GBK"),"iso-8859-1"));     
  146.             byte[] bytes = new byte[1024];     
  147.             long step = lRemoteSize /100;     
  148.             long process=0;     
  149.             long localSize = 0L;     
  150.             int c;     
  151.             while((c = in.read(bytes))!= -1){     
  152.                 out.write(bytes, 0, c);     
  153.                 localSize+=c;     
  154.                 long nowProcess = localSize /step;     
  155.                 if(nowProcess > process){     
  156.                     process = nowProcess;     
  157.                     if(process % 10 == 0)     
  158.                         System.out.println("下载进度:"+process);     
  159.                     //TODO 更新文件下载进度,值存放在process变量中     
  160.                 }     
  161.             }     
  162.             in.close();     
  163.             out.close();     
  164.             boolean upNewStatus = ftpClient.completePendingCommand();     
  165.             if(upNewStatus){     
  166.                 result = DownloadStatus.Download_New_Success;     
  167.             }else {     
  168.                 result = DownloadStatus.Download_New_Failed;     
  169.             }     
  170.         }     
  171.         return result;     
  172.     }     
  173.          
  174.     /** *//**   
  175.      * 上传文件到FTP服务器,支持断点续传   
  176.      * @param local 本地文件名称,绝对路径   
  177.      * @param remote 远程文件路径,使用/home/directory1/subdirectory/file.ext或是 http://www.guihua.org /subdirectory/file.ext 按照Linux上的路径指定方式,支持多级目录嵌套,支持递归创建不存在的目录结构   
  178.      * @return 上传结果   
  179.      * @throws IOException   
  180.      */    
  181.     public UploadStatus upload(String local,String remote) throws IOException{     
  182.         //设置PassiveMode传输     
  183.         ftpClient.enterLocalPassiveMode();     
  184.         //设置以二进制流的方式传输     
  185.         ftpClient.setFileType(FTP.BINARY_FILE_TYPE);     
  186.         ftpClient.setControlEncoding("GBK");     
  187.         UploadStatus result;     
  188.         //对远程目录的处理     
  189.         String remoteFileName = remote;     
  190.         if(remote.contains("/")){     
  191.             remoteFileName = remote.substring(remote.lastIndexOf("/")+1);     
  192.             //创建服务器远程目录结构,创建失败直接返回     
  193.             if(CreateDirecroty(remote, ftpClient)==UploadStatus.Create_Directory_Fail){     
  194.                 return UploadStatus.Create_Directory_Fail;     
  195.             }     
  196.         }     
  197.              
  198.         //检查远程是否存在文件     
  199.         FTPFile[] files = ftpClient.listFiles(new String(remoteFileName.getBytes("GBK"),"iso-8859-1"));     
  200.         if(files.length == 1){     
  201.             long remoteSize = files[0].getSize();     
  202.             File f = new File(local);     
  203.             long localSize = f.length();     
  204.             if(remoteSize==localSize){     
  205.                 return UploadStatus.File_Exits;     
  206.             }else if(remoteSize > localSize){     
  207.                 return UploadStatus.Remote_Bigger_Local;     
  208.             }     
  209.                  
  210.             //尝试移动文件内读取指针,实现断点续传     
  211.             result = uploadFile(remoteFileName, f, ftpClient, remoteSize);     
  212.                  
  213.             //如果断点续传没有成功,则删除服务器上文件,重新上传     
  214.             if(result == UploadStatus.Upload_From_Break_Failed){     
  215.                 if(!ftpClient.deleteFile(remoteFileName)){     
  216.                     return UploadStatus.Delete_Remote_Faild;     
  217.                 }     
  218.                 result = uploadFile(remoteFileName, f, ftpClient, 0);     
  219.             }     
  220.         }else {     
  221.             result = uploadFile(remoteFileName, new File(local), ftpClient, 0);     
  222.         }     
  223.         return result;     
  224.     }     
  225.     /** *//**   
  226.      * 断开与远程服务器的连接   
  227.      * @throws IOException   
  228.      */    
  229.     public void disconnect() throws IOException{     
  230.         if(ftpClient.isConnected()){     
  231.             ftpClient.disconnect();     
  232.         }     
  233.     }     
  234.          
  235.     /** *//**   
  236.      * 递归创建远程服务器目录   
  237.      * @param remote 远程服务器文件绝对路径   
  238.      * @param ftpClient FTPClient 对象   
  239.      * @return 目录创建是否成功   
  240.      * @throws IOException   
  241.      */    
  242.     public UploadStatus CreateDirecroty(String remote,FTPClient ftpClient) throws IOException{     
  243.         UploadStatus status = UploadStatus.Create_Directory_Success;     
  244.         String directory = remote.substring(0,remote.lastIndexOf("/")+1);     
  245.         if(!directory.equalsIgnoreCase("/")&&!ftpClient.changeWorkingDirectory(new String(directory.getBytes("GBK"),"iso-8859-1"))){     
  246.             //如果远程目录不存在,则递归创建远程服务器目录     
  247.             int start=0;     
  248.             int end = 0;     
  249.             if(directory.startsWith("/")){     
  250.                 start = 1;     
  251.             }else{     
  252.                 start = 0;     
  253.             }     
  254.             end = directory.indexOf("/",start);     
  255.             while(true){     
  256.                 String subDirectory = new String(remote.substring(start,end).getBytes("GBK"),"iso-8859-1");     
  257.                 if(!ftpClient.changeWorkingDirectory(subDirectory)){     
  258.                     if(ftpClient.makeDirectory(subDirectory)){     
  259.                         ftpClient.changeWorkingDirectory(subDirectory);     
  260.                     }else {     
  261.                         System.out.println("创建目录失败");     
  262.                         return UploadStatus.Create_Directory_Fail;     
  263.                     }     
  264.                 }     
  265.                      
  266.                 start = end + 1;     
  267.                 end = directory.indexOf("/",start);     
  268.                      
  269.                 //检查所有目录是否创建完毕     
  270.                 if(end <= start){     
  271.                     break;     
  272.                 }     
  273.             }     
  274.         }     
  275.         return status;     
  276.     }     
  277.          
  278.     /** *//**   
  279.      * 上传文件到服务器,新上传和断点续传   
  280.      * @param remoteFile 远程文件名,在上传之前已经将服务器工作目录做了改变   
  281.      * @param localFile 本地文件 File句柄,绝对路径   
  282.      * @param processStep 需要显示的处理进度步进值   
  283.      * @param ftpClient FTPClient 引用   
  284.      * @return   
  285.      * @throws IOException   
  286.      */    
  287.     public UploadStatus uploadFile(String remoteFile,File localFile,FTPClient ftpClient,long remoteSize) throws IOException{     
  288.         UploadStatus status;     
  289.         //显示进度的上传     
  290.         long step = localFile.length() / 100;     
  291.         long process = 0;     
  292.         long localreadbytes = 0L;     
  293.         RandomAccessFile raf = new RandomAccessFile(localFile,"r");     
  294.         OutputStream out = ftpClient.appendFileStream(new String(remoteFile.getBytes("GBK"),"iso-8859-1"));     
  295.         //断点续传     
  296.         if(remoteSize>0){     
  297.             ftpClient.setRestartOffset(remoteSize);     
  298.             process = remoteSize /step;     
  299.             raf.seek(remoteSize);     
  300.             localreadbytes = remoteSize;     
  301.         }     
  302.         byte[] bytes = new byte[1024];     
  303.         int c;     
  304.         while((c = raf.read(bytes))!= -1){     
  305.             out.write(bytes,0,c);     
  306.             localreadbytes+=c;     
  307.             if(localreadbytes / step != process){     
  308.                 process = localreadbytes / step;     
  309.                 System.out.println("上传进度:" + process);     
  310.                 //TODO 汇报上传状态     
  311.             }     
  312.         }     
  313.         out.flush();     
  314.         raf.close();     
  315.         out.close();     
  316.         boolean result =ftpClient.completePendingCommand();     
  317.         if(remoteSize > 0){     
  318.             status = result?UploadStatus.Upload_From_Break_Success:UploadStatus.Upload_From_Break_Failed;     
  319.         }else {     
  320.             status = result?UploadStatus.Upload_New_File_Success:UploadStatus.Upload_New_File_Failed;     
  321.         }     
  322.         return status;     
  323.     }     
  324.          
  325.       
  326.     @Test   
  327.      
  328. public void run() {   
  329.   // TODO Auto-generated method stub   
  330.       
  331.          try {     
  332.           this.connect(ftpURL, new java.lang.Integer(ftpport), username, pwd);   
  333. //           myFtp.ftpClient.makeDirectory(new String(" 电视剧".getBytes("GBK"),"iso-8859-1"));     
  334. //           myFtp.ftpClient.changeWorkingDirectory(new String(" 电视剧".getBytes("GBK"),"iso-8859-1"));     
  335. //           myFtp.ftpClient.makeDirectory(new String(" 走西口".getBytes("GBK"),"iso-8859-1"));     
  336. //           System.out.println(myFtp.upload("http://www.5a520.cn /yw.flv", "/yw.flv",5));     
  337. //           System.out.println(myFtp.upload("http://www.5a520.cn /走西口24.mp4","/央视走西口/新浪网/走西口 24.mp4"));     
  338.           //   System.out.println(myFtp.download("/ 央视走西口/新浪网/走西口24.mp4", "E:\\走西口242.mp4"));   
  339.             
  340.            this.download(file1, file2);   
  341.          //  System.out.println(myFtp.upload("c:\\a.iso", "/a.iso"));   
  342.              this.disconnect();     
  343.          } catch (IOException e) {     
  344.              System.out.println("连接FTP出错:"+e.getMessage());     
  345.          }     
  346. }     
0 0
原创粉丝点击