免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1058 | 回复: 0
打印 上一主题 下一主题

用Java实现FTP批量大文件上传下载(二) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-06-25 12:31 |只看该作者 |倒序浏览
[color="#ff0000"]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);

        }

    }



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

[color="#ff0000"]四、  进度条

可以想象,如果在上传或是下载的过程中,没有任何的提示,用户根本没法判断任务是否完成或是任务是否死了,常常由于上传时间或下载时间过长而误导用户。因此,进度条就显得非常的重要与实用。
进度条的实现,其实说起来很简单。就是在程序中开启两个线程,第一个线程用于动态的改变界面上进度条的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则变化不是特别明显。
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/20282/showart_1010981.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP