posts - 310, comments - 6939, trackbacks - 0, articles - 3
  BlogJava :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

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

Posted on 2007-10-22 09:43 诗特林 阅读(11563) 评论(15)  编辑  收藏 所属分类: Socket
                                        用Java实现FTP批量大文件上传下载(二) 

  • 用Java实现FTP批量大文件上传下载(六)--代码及示例下载
  • 用Java实现FTP批量大文件上传下载(五) --运行效果图
  • 用Java实现FTP批量大文件上传下载(四)
  • 用Java实现FTP批量大文件上传下载(三)
  • 用Java实现FTP批量大文件上传下载(二)
  • 用Java实现FTP批量大文件上传下载(一)
     
  • 2 上传下载

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

    public int handleUpload(String file, String realName)
        
    {
            
    if(Settings.getEnableMultiThreading() &&
                   (
    !Settings.getNoUploadMultiThreading()))
            
    {
                Log.out(
    "spawning new thread for this upload.");

                FtpTransfer t;

                
    if(realName != null)
                
    {
                    t 
    = new FtpTransfer(host, port, getLocalPath(), getCachedPWD(),
                                        file, username, password, Transfer.UPLOAD,
                                        handler, listeners, realName, crlf);
                }

                
    else
                
    {
                    t 
    = new FtpTransfer(host, port, getLocalPath(), getCachedPWD(),
                                        file, username, password, Transfer.UPLOAD,
                                        handler, listeners, crlf);
                }


                lastTransfer 
    = t;

                
    return NEW_TRANSFER_SPAWNED;
            }

            
    else
            
    {
                
    if(Settings.getNoUploadMultiThreading())
                
    {
                    Log.out(
    "upload multithreading is disabled.");
                }

                
    else
                
    {
                    Log.out(
    "multithreading is completely disabled.");
                }


                
    return (realName == null? upload(file) : upload(file, realName);
            }

    }


     

    在多线程的情况下,有一个单独的类net.sf.jftp.net .FtpTransfer,当然,多线程情况下,此类肯定是一个单独的线程了。与JConnection相似,其线程的启动也是在构造方法中启动。而在它的run方法中,进行文件的读取及传输。

    public void run()
        
    {
            
    if(handler.getConnections().get(file) == null)
            
    {
                handler.addConnection(file, 
    this);
            }

            
    else if(!pause)
            
    {
                Log.debug(
    "Transfer already in progress: " + file);
                work 
    = false;
                stat 
    = 2;

                
    return;
            }


            
    boolean hasPaused = false;

            
    while(pause)
            
    {
                
    try
                
    {
                    runner.sleep(
    100);

                    
    if(listeners != null)
                    
    {
                        
    for(int i = 0; i < listeners.size(); i++)
                        
    {
                            ((ConnectionListener) listeners.elementAt(i)).updateProgress(file,
                                                                                         PAUSED,
                                                                                         
    -1);
                        }

                    }


                    
    if(!work)
                    
    {
                        
    if(listeners != null)
                        
    {
                            
    for(int i = 0; i < listeners.size(); i++)
                            
    {
                                ((ConnectionListener) listeners.elementAt(i)).updateProgress(file,
                                                                                             REMOVED,
                                                                                             
    -1);
                            }

                        }

                    }

                }

                
    catch(Exception ex)
                
    {
                }


                hasPaused 
    = true;
            }


            
    while((handler.getConnectionSize() >= Settings.getMaxConnections()) &&
                      (handler.getConnectionSize() 
    > 0&& work)
            
    {
                
    try
                
    {
                    stat 
    = 4;
                    runner.sleep(
    400);

                    
    if(!hasPaused && (listeners != null))
                    
    {
                        
    for(int i = 0; i < listeners.size(); i++)
                        
    {
                            ((ConnectionListener) listeners.elementAt(i)).updateProgress(file,
                                                                                         QUEUED,
                                                                                         
    -1);
                        }

                    }

                    
    else
                    
    {
                        
    break;
                    }

                }

                
    catch(Exception ex)
                
    {
                    ex.printStackTrace();
                }

            }


            
    if(!work)
            
    {
                
    if(listeners != null)
                
    {
                    
    for(int i = 0; i < listeners.size(); i++)
                    
    {
                        ((ConnectionListener) listeners.elementAt(i)).updateProgress(file,
                                                                                     REMOVED,
                                                                                     
    -1);
                    }

                }


                handler.removeConnection(file);
                stat 
    = 3;

                
    return;
            }


            started 
    = true;

            
    try
            
    {
                runner.sleep(Settings.ftpTransferThreadPause);
            }

            
    catch(Exception ex)
            
    {
            }


            con 
    = new FtpConnection(host, port, remotePath, crlf);

            con.setConnectionHandler(handler);
            con.setConnectionListeners(listeners);

            
    int status = con.login(user, pass);

            
    if(status == FtpConnection.LOGIN_OK)
            
    {
                File f 
    = new File(localPath);
                con.setLocalPath(f.getAbsolutePath());

                
    if(type.equals(UPLOAD))
                
    {
                    
    if(newName != null)
                    
    {
                        transferStatus 
    = con.upload(file, newName);
                    }

                    
    else
                    
    {
                        transferStatus 
    = con.upload(file);
                    }

                }

                
    else
                
    {
                    transferStatus 
    = con.download(file,this.newName);
                }

            }


            
    if(!pause)
            
    {
                handler.removeConnection(file);
            }

        }



     

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

     

      进度条

     

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

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

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

        public int upload(String file, String realName, InputStream in)
        
    {
            hasUploaded 
    = true;
            Log.out(
    "ftp upload started: " + this);

            
    int stat;

            
    if((in == null&& new File(file).isDirectory())
            
    {
                shortProgress 
    = true;
                fileCount 
    = 0;
                baseFile 
    = file;
                dataType 
    = DataConnection.PUTDIR;
                isDirUpload 
    = true;

                stat 
    = uploadDir(file);

                shortProgress 
    = false;

                
    //System.out.println(fileCount + ":" + baseFile);
                fireProgressUpdate(baseFile,
                                   DataConnection.DFINISHED 
    + ":" + fileCount, -1);

                fireActionFinished(
    this);
                fireDirectoryUpdate(
    this);
            }

            
    else
            
    {
                dataType 
    = DataConnection.PUT;
                stat 
    = rawUpload(file, realName, in);

                
    try
                
    {
                    Thread.sleep(
    100);
                }

                
    catch(Exception ex)
                
    {
                }


                fireActionFinished(
    this);
                fireDirectoryUpdate(
    this);
            }


            
    try
            
    {
                Thread.sleep(
    500);
            }

            
    catch(Exception ex)
            
    {
            }


            
    return stat;
        }


     

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

        protected void updateProgressBar() {
            
    int percent = (int) (((float) lFileCompleteSize / (float) lFileSize) * 10000F);
            pbFile.setValue(percent);
            
    // System.out.println("================================================="+percent);
            pbFile.setString(lFileCompleteSize / 1024L + "/" + lFileSize / 1024L
                    
    + " kB");
            percent 
    = (int) (((float) lTotalCompleteSize / (float) lTotalSize) * 10000F);
            pbTotal.setString(lTotalCompleteSize 
    / 1024L + "/" + lTotalSize / 1024L
                    
    + " kB");
            pbTotal.setValue(percent);
            repaint();
        }

     

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


    评论

    # re: 用Java实现FTP批量大文件上传下载(二)   回复  更多评论   

    2007-11-12 11:12 by figo
    有没有源码啊

    # re: 用Java实现FTP批量大文件上传下载(二)   回复  更多评论   

    2007-12-12 18:02 by luciano
    可以详细讲一下进度条的内容吗?我如何才能显示进度条?能否给个加进度条的例子

    # re: 用Java实现FTP批量大文件上传下载(二) [未登录]  回复  更多评论   

    2007-12-14 17:22 by 王磊
    大哥,能给个全部的源码么?我看了你的演示,很不错,适合我现在的需求,万分感谢!我的邮箱是 wangl@95068.com

    # re: 用Java实现FTP批量大文件上传下载(二)   回复  更多评论   

    2008-06-16 15:28 by 逸诚
    哥们,非常佩服你的才华。非常棒,能否将全部源码和文档给我发一份,我认真学习一下,不胜感激之至。我的邮箱是jnflxdx@163.com或者519899460@qq.com。

    # re: 用Java实现FTP批量大文件上传下载(二) [未登录]  回复  更多评论   

    2009-02-05 23:18 by liwei
    哥们,非常佩服你的才华。非常棒,能否将全部源码和文档给我发一份,我认真学习一下,不胜感激之至。我的邮箱是109626532@163.com

    # re: 用Java实现FTP批量大文件上传下载(二)   回复  更多评论   

    2009-07-11 21:37 by
    楼主,太强了。能不能让我也学习一下。能发份源代码给我吗?我的邮箱是408985552@qq.com,不甚感激!!

    # re: 用Java实现FTP批量大文件上传下载(二)   回复  更多评论   

    2011-01-14 14:18 by Glorin
    楼主你好哇?看了你的演示非常棒!你可以把全部源码都发一份给我吗?我好好研究一下,非常感谢。我的邮箱是350643976@qq.com

    # re: 用Java实现FTP批量大文件上传下载(二)   回复  更多评论   

    2011-09-02 11:09 by 徐强
    能否发一份源码给我.万分感谢!qiangzi1110@126.com

    # re: 用Java实现FTP批量大文件上传下载(二)   回复  更多评论   

    2011-09-15 21:50 by 维拉斯
    楼主,太强了。能不能让我也学习一下。能发份源代码给我吗?我的邮箱是yushuffoo@163.com,不甚感激!!

    # re: 用Java实现FTP批量大文件上传下载(二)   回复  更多评论   

    2012-01-14 14:41 by 婷婷
    跪求一份全部源码,不甚感激,着急使用谢谢啦!1936330494@qq.com

    # re: 用Java实现FTP批量大文件上传下载(二)   回复  更多评论   

    2012-05-22 16:32 by shanyiyatou
    为什么上传的时候会有乱码呢

    # re: 用Java实现FTP批量大文件上传下载(二) [未登录]  回复  更多评论   

    2012-08-05 10:00 by derekzhan
    兄弟能不能给我传一份源码~ zhanweichun@126.com 不胜感激!!

    # re: 用Java实现FTP批量大文件上传下载(二)   回复  更多评论   

    2013-05-18 21:57 by 岳晓西
    楼主,您好,能否给俺也发一份呀,学习,不慎感激 邮箱:949752584@qq.com

    # re: 用Java实现FTP批量大文件上传下载(二) [未登录]  回复  更多评论   

    2013-09-30 09:23 by 小白
    718589908@qq.com 坐等

    # re: 用Java实现FTP批量大文件上传下载(二)   回复  更多评论   

    2014-11-09 22:28 by 马成虎
    楼主能给菜鸟发一份吗? 邮箱:2425643701@qq.com

    只有注册用户登录后才能发表评论。


    网站导航: