分享

用Java实现FTP批量大文件上传下载(二)

 WindySky 2016-04-18


上传下载

文件的上传可以分成多线程及单线程,在单线程情况下比较简单,而在多线程的情况下,要处理的事情要多点,同时也要小心很多。下面是net.sf.jftp.net.FtpConnection的上传handleUpload方法。已经考虑了单线程及多线程两种不同的类型。

  1. public int handleUpload(String file, String realName)  
  2.     {  
  3.         if(Settings.getEnableMultiThreading() &&  
  4.                (!Settings.getNoUploadMultiThreading()))  
  5.         {  
  6.             Log.out("spawning new thread for this upload.");  
  7.   
  8.             FtpTransfer t;  
  9.   
  10.             if(realName != null)  
  11.             {  
  12.                 t = new FtpTransfer(host, port, getLocalPath(), getCachedPWD(),  
  13.                                     file, username, password, Transfer.UPLOAD,  
  14.                                     handler, listeners, realName, crlf);  
  15.             }  
  16.             else  
  17.             {  
  18.                 t = new FtpTransfer(host, port, getLocalPath(), getCachedPWD(),  
  19.                                     file, username, password, Transfer.UPLOAD,  
  20.                                     handler, listeners, crlf);  
  21.             }  
  22.   
  23.             lastTransfer = t;  
  24.   
  25.             return NEW_TRANSFER_SPAWNED;  
  26.         }  
  27.         else  
  28.         {  
  29.             if(Settings.getNoUploadMultiThreading())  
  30.             {  
  31.                 Log.out("upload multithreading is disabled.");  
  32.             }  
  33.             else  
  34.             {  
  35.                 Log.out("multithreading is completely disabled.");  
  36.             }  
  37.   
  38.             return (realName == null) ? upload(file) : upload(file, realName);  
  39.         }  
  40. }  


    在多线程的情况下,有一个单独的类net.sf.jftp.net .FtpTransfer,当然,多线程情况下,此类肯定是一个单独的线程了。与JConnection相似,其线程的启动也是在构造方法中启动。而在它的run方法中,进行文件的读取及传输。
  1. public void run()  
  2.     {  
  3.         if(handler.getConnections().get(file) == null)  
  4.         {  
  5.             handler.addConnection(file, this);  
  6.         }  
  7.         else if(!pause)  
  8.         {  
  9.             Log.debug("Transfer already in progress: " + file);  
  10.             work = false;  
  11.             stat = 2;  
  12.   
  13.             return;  
  14.         }  
  15.   
  16.         boolean hasPaused = false;  
  17.   
  18.         while(pause)  
  19.         {  
  20.             try  
  21.             {  
  22.                 runner.sleep(100);  
  23.   
  24.                 if(listeners != null)  
  25.                 {  
  26.                     for(int i = 0; i < listeners.size(); i++)  
  27.                     {  
  28.                         ((ConnectionListener) listeners.elementAt(i)).updateProgress(file,  
  29.                                                                                      PAUSED,  
  30.                                                                                      -1);  
  31.                     }  
  32.                 }  
  33.   
  34.                 if(!work)  
  35.                 {  
  36.                     if(listeners != null)  
  37.                     {  
  38.                         for(int i = 0; i < listeners.size(); i++)  
  39.                         {  
  40.                             ((ConnectionListener) listeners.elementAt(i)).updateProgress(file,  
  41.                                                                                          REMOVED,  
  42.                                                                                          -1);  
  43.                         }  
  44.                     }  
  45.                 }  
  46.             }  
  47.             catch(Exception ex)  
  48.             {  
  49.             }  
  50.   
  51.             hasPaused = true;  
  52.         }  
  53.   
  54.         while((handler.getConnectionSize() >= Settings.getMaxConnections()) &&  
  55.                   (handler.getConnectionSize() > 0) && work)  
  56.         {  
  57.             try  
  58.             {  
  59.                 stat = 4;  
  60.                 runner.sleep(400);  
  61.   
  62.                 if(!hasPaused && (listeners != null))  
  63.                 {  
  64.                     for(int i = 0; i < listeners.size(); i++)  
  65.                     {  
  66.                         ((ConnectionListener) listeners.elementAt(i)).updateProgress(file,  
  67.                                                                                      QUEUED,  
  68.                                                                                      -1);  
  69.                     }  
  70.                 }  
  71.                 else  
  72.                 {  
  73.                     break;  
  74.                 }  
  75.             }  
  76.             catch(Exception ex)  
  77.             {  
  78.                 ex.printStackTrace();  
  79.             }  
  80.         }  
  81.   
  82.         if(!work)  
  83.         {  
  84.             if(listeners != null)  
  85.             {  
  86.                 for(int i = 0; i < listeners.size(); i++)  
  87.                 {  
  88.                     ((ConnectionListener) listeners.elementAt(i)).updateProgress(file,  
  89.                                                                                  REMOVED,  
  90.                                                                                  -1);  
  91.                 }  
  92.             }  
  93.   
  94.             handler.removeConnection(file);  
  95.             stat = 3;  
  96.   
  97.             return;  
  98.         }  
  99.   
  100.         started = true;  
  101.   
  102.         try  
  103.         {  
  104.             runner.sleep(Settings.ftpTransferThreadPause);  
  105.         }  
  106.         catch(Exception ex)  
  107.         {  
  108.         }  
  109.   
  110.         con = new FtpConnection(host, port, remotePath, crlf);  
  111.   
  112.         con.setConnectionHandler(handler);  
  113.         con.setConnectionListeners(listeners);  
  114.   
  115.         int status = con.login(user, pass);  
  116.   
  117.         if(status == FtpConnection.LOGIN_OK)  
  118.         {  
  119.             File f = new File(localPath);  
  120.             con.setLocalPath(f.getAbsolutePath());  
  121.   
  122.             if(type.equals(UPLOAD))  
  123.             {  
  124.                 if(newName != null)  
  125.                 {  
  126.                     transferStatus = con.upload(file, newName);  
  127.                 }  
  128.                 else  
  129.                 {  
  130.                     transferStatus = con.upload(file);  
  131.                 }  
  132.             }  
  133.             else  
  134.             {  
  135.                 transferStatus = con.download(file,this.newName);  
  136.             }  
  137.         }  
  138.   
  139.         if(!pause)  
  140.         {  
  141.             handler.removeConnection(file);  
  142.         }  
  143.     }  


至于下载的过程,因为它是上传的逆过程,与上传的方法及写法大同小异,在些出于篇幅的考虑,并没有将代码列出,但其思想及思路完全一样。请读者参考源代码。

 

、  进度条

 

可以想象,如果在上传或是下载的过程中,没有任何的提示,用户根本没法判断任务是否完成或是任务是否死了,常常由于上传时间或下载时间过长而误导用户。因此,进度条就显得非常的重要与实用。

进度条的实现,其实说起来很简单。就是在程序中开启两个线程,第一个线程用于动态的改变界面上进度条的value值,而第二个线程则在上传或是下载的过程中,做成一个循环,在此循环中,每次读取一定数量如8192字节数的数据。然后传完此数据后,调用第一个线程中的updateProgress方法,来更新界面进度条的value值。

而上传或下载的过程中(见上一节的FtpTransfer类的run方法),可以查看,con.upload(file, newName)方法,代码如下所示,

  1. public int upload(String file, String realName, InputStream in)  
  2.     {  
  3.         hasUploaded = true;  
  4.         Log.out("ftp upload started: " + this);  
  5.   
  6.         int stat;  
  7.   
  8.         if((in == null) && new File(file).isDirectory())  
  9.         {  
  10.             shortProgress = true;  
  11.             fileCount = 0;  
  12.             baseFile = file;  
  13.             dataType = DataConnection.PUTDIR;  
  14.             isDirUpload = true;  
  15.   
  16.             stat = uploadDir(file);  
  17.   
  18.             shortProgress = false;  
  19.   
  20.             //System.out.println(fileCount + ":" + baseFile);  
  21.             fireProgressUpdate(baseFile,  
  22.                                DataConnection.DFINISHED + ":" + fileCount, -1);  
  23.   
  24.             fireActionFinished(this);  
  25.             fireDirectoryUpdate(this);  
  26.         }  
  27.         else  
  28.         {  
  29.             dataType = DataConnection.PUT;  
  30.             stat = rawUpload(file, realName, in);  
  31.   
  32.             try  
  33.             {  
  34.                 Thread.sleep(100);  
  35.             }  
  36.             catch(Exception ex)  
  37.             {  
  38.             }  
  39.   
  40.             fireActionFinished(this);  
  41.             fireDirectoryUpdate(this);  
  42.         }  
  43.   
  44.         try  
  45.         {  
  46.             Thread.sleep(500);  
  47.         }  
  48.         catch(Exception ex)  
  49.         {  
  50.         }  
  51.   
  52.         return stat;  
  53.     }  


此方法进行负责上传一定字节数量的内容,其实就是调用
rawUpload方法,这里没列出,请参考源代码,而当传完此字节数据后,通过调用fireActionFinished()方法来调用主线程中的updateProgressBar()。其实代码如下:

  1. protected void updateProgressBar() {  
  2.      int percent = (int) (((float) lFileCompleteSize / (float) lFileSize) * 10000F);  
  3.      pbFile.setValue(percent);  
  4.      // System.out.println("================================================="+percent);  
  5.      pbFile.setString(lFileCompleteSize / 1024L + "/" + lFileSize / 1024L  
  6.              + " kB");  
  7.      percent = (int) (((float) lTotalCompleteSize / (float) lTotalSize) * 10000F);  
  8.      pbTotal.setString(lTotalCompleteSize / 1024L + "/" + lTotalSize / 1024L  
  9.              + " kB");  
  10.      pbTotal.setValue(percent);  
  11.      repaint();  
  12.  }  


上面用了两个进度条,第一个进度条表示当前文件的上传或下载进度,第二个进度条表示所有文件下载或上传的进度。同时,为了产生进度条的移动或变化进度幅度比较明显,通过
pbFile.setMaximum(10000)pbTotal.setMaximum(10000)将进度条的最大值设置成10000,而不是平时我们所设置的100。笔者认为这样比较好看,因为有的时候上传或下载的时候由于网络原因,可能变化比较小。若设置成100则变化不是特别明显。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多