- 论坛徽章:
- 0
|
[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 |
|