- 论坛徽章:
- 0
|
五、断点续传
对于熟用QQ的程序员,QQ的断点续传功能应该是印象很深刻的。因为它很实用也很方面。因此,在我们的上传下载过程中,很实现了断点续传的功能。
其实断点续传的原理很简单,就在上传的过程中,先去服务上进行查找,是否存在此文件,如果存在些文件,则比较服务器上文件的大小与本地文件的大小,如果服务器上的文件比本地的要小,则认为此文件上传过程中应该可以进行断点续传。
在实现的过程中,RandomAccessFile类变得很有用。此类的实例支持对随机存取文件的读取和写入。随机存取文件的行为类似存储在文件系统中的一个大型字节数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机存取文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法进行设置。
RandomAccessFile类的skipBytes方法尝试跳过输入的 n 个字节以丢弃跳过的字节。如果从服务器上查得待上传文件的大小n,则采用skipBytes方法可以跳过这n个字节,从而开始从新的地方开始进行断点续传。具体的方法说明可以参见JDK5的API说明。
可以在net.sf.jftp.net. DataConnection类的run方法中,可以看出上传下载中断点续传的实现,代码如下:
![]()
public void run()
![]()
![]()
![]()
{
![]()
try
![]()
![]()
![]()
{
![]()
newLine = con.getCRLF();
![]()
![]()
if(Settings.getFtpPasvMode())
![]()
![]()
![]()
{
![]()
try
![]()
![]()
![]()
{
![]()
sock = new Socket(host, port);
![]()
sock.setSoTimeout(Settings.getSocketTimeout());
![]()
}
![]()
catch(Exception ex)
![]()
![]()
![]()
{
![]()
ok = false;
![]()
debug("Can't open Socket on port " + port);
![]()
}
![]()
}
![]()
else
![]()
![]()
![]()
{
![]()
//Log.debug("trying new server socket: "+port);
![]()
try
![]()
![]()
![]()
{
![]()
ssock = new ServerSocket(port);
![]()
}
![]()
catch(Exception ex)
![]()
![]()
![]()
{
![]()
ok = false;
![]()
Log.debug("Can't open ServerSocket on port " + port);
![]()
}
![]()
}
![]()
}
![]()
catch(Exception ex)
![]()
![]()
![]()
{
![]()
debug(ex.toString());
![]()
}
![]()
![]()
isThere = true;
![]()
![]()
boolean ok = true;
![]()
![]()
RandomAccessFile fOut = null;
![]()
BufferedOutputStream bOut = null;
![]()
RandomAccessFile fIn = null;
![]()
![]()
try
![]()
![]()
![]()
{
![]()
if(!Settings.getFtpPasvMode())
![]()
![]()
![]()
{
![]()
int retry = 0;
![]()
![]()
while((retry++ 5) && (sock == null))
![]()
![]()
![]()
{
![]()
try
![]()
![]()
![]()
{
![]()
ssock.setSoTimeout(Settings.connectionTimeout);
![]()
sock = ssock.accept();
![]()
}
![]()
catch(IOException e)
![]()
![]()
![]()
{
![]()
sock = null;
![]()
debug("Got IOException while trying to open a socket!");
![]()
![]()
if(retry == 5)
![]()
![]()
![]()
{
![]()
debug("Connection failed, tried 5 times - maybe try a higher timeout in Settings.java
![]()
");
![]()
}
![]()
![]()
finished = true;
![]()
![]()
throw e;
![]()
}
![]()
finally
![]()
![]()
![]()
{
![]()
ssock.close();
![]()
}
![]()
![]()
debug("Attempt timed out, retrying
![]()
");
![]()
}
![]()
}
![]()
![]()
if(ok)
![]()
![]()
![]()
{
![]()
byte[] buf = new byte[Settings.bufferSize];
![]()
start = System.currentTimeMillis();
![]()
![]()
int buflen = 0;
![]()
![]()
//---------------download,下载----------------------
![]()
if(type.equals(GET) || type.equals(GETDIR))
![]()
![]()
![]()
{
![]()
if(!justStream)
![]()
![]()
![]()
{
![]()
try
![]()
![]()
![]()
{
![]()
if(resume)
![]()
![]()
![]()
{
![]()
File f = new File(file);
![]()
fOut = new RandomAccessFile(file, "rw");
![]()
fOut.skipBytes((int) f.length());
![]()
buflen = (int) f.length();
![]()
}
![]()
else
![]()
![]()
![]()
{
![]()
if(localfile == null)
![]()
![]()
![]()
{
![]()
localfile = file;
![]()
}
![]()
![]()
File f2 = new File(Settings.appHomeDir);
![]()
f2.mkdirs();
![]()
![]()
File f = new File(localfile);
![]()
![]()
if(f.exists())
![]()
![]()
![]()
{
![]()
f.delete();
![]()
}
![]()
![]()
bOut = new BufferedOutputStream(new FileOutputStream(localfile),
![]()
Settings.bufferSize);
![]()
}
![]()
}
![]()
catch(Exception ex)
![]()
![]()
![]()
{
![]()
debug("Can't create outputfile: " + file);
![]()
ok = false;
![]()
ex.printStackTrace();
![]()
}
![]()
}
![]()
![]()
![]()
//---------------upload,上传----------------------
![]()
if(type.equals(PUT) || type.equals(PUTDIR))
![]()
![]()
![]()
{
![]()
if(in == null)
![]()
![]()
![]()
{
![]()
try
![]()
![]()
![]()
{
![]()
fIn = new RandomAccessFile(file, "r");
![]()
![]()
if(resume)
![]()
![]()
![]()
{
![]()
fIn.skipBytes(skiplen);
![]()
}
![]()
![]()
//fIn = new BufferedInputStream(new FileInputStream(file));
![]()
}
![]()
catch(Exception ex)
![]()
![]()
![]()
{
![]()
debug("Can't open inputfile: " + " (" + ex + ")");
![]()
ok = false;
![]()
}
![]()
}
![]()
![]()
if(ok)
![]()
![]()
![]()
{
![]()
try
![]()
![]()
![]()
{
![]()
out = new BufferedOutputStream(sock.getOutputStream());
![]()
}
![]()
catch(Exception ex)
![]()
![]()
![]()
{
![]()
ok = false;
![]()
debug("Can't get OutputStream");
![]()
}
![]()
![]()
if(ok)
![]()
![]()
![]()
{
![]()
try
![]()
![]()
![]()
{
![]()
int len = skiplen;
![]()
char b;
![]()
![]()
while(true)
![]()
![]()
![]()
{
![]()
int read;
![]()
![]()
if(in != null)
![]()
![]()
![]()
{
![]()
read = in.read(buf);
![]()
}
![]()
else
![]()
![]()
![]()
{
![]()
read = fIn.read(buf);
![]()
}
![]()
![]()
len += read;
![]()
![]()
//System.out.println(file + " " + type+ " " + len + " " + read);
![]()
if(read == -1)
![]()
![]()
![]()
{
![]()
break;
![]()
}
![]()
![]()
if(newLine != null)
![]()
![]()
![]()
{
![]()
byte[] buf2 = modifyPut(buf, read);
![]()
out.write(buf2, 0, buf2.length);
![]()
}
![]()
else
![]()
![]()
![]()
{
![]()
out.write(buf, 0, read);
![]()
}
![]()
![]()
con.fireProgressUpdate(file, type, len);
![]()
![]()
if(time())
![]()
![]()
![]()
{
![]()
// Log.debugSize(len, false, false, file);
![]()
}
![]()
![]()
if(read == StreamTokenizer.TT_EOF)
![]()
![]()
![]()
{
![]()
break;
![]()
}
![]()
}
![]()
![]()
out.flush();
![]()
![]()
//Log.debugSize(len, false, true, file);
![]()
}
![]()
catch(IOException ex)
![]()
![]()
![]()
{
![]()
ok = false;
![]()
debug("Error: Data connection closed.");
![]()
con.fireProgressUpdate(file, FAILED, -1);
![]()
ex.printStackTrace();
![]()
}
![]()
}
![]()
}
![]()
}
![]()
}
![]()
}
![]()
catch(IOException ex)
![]()
![]()
![]()
{
![]()
Log.debug("Can't connect socket to ServerSocket");
![]()
ex.printStackTrace();
![]()
}
![]()
finally
![]()
![]()
![]()
{
![]()
try
![]()
![]()
![]()
{
![]()
if(out != null)
![]()
![]()
![]()
{
![]()
out.flush();
![]()
out.close();
![]()
}
![]()
}
![]()
catch(Exception ex)
![]()
![]()
![]()
{
![]()
ex.printStackTrace();
![]()
}
![]()
![]()
try
![]()
![]()
![]()
{
![]()
if(bOut != null)
![]()
![]()
![]()
{
![]()
bOut.flush();
![]()
bOut.close();
![]()
}
![]()
}
![]()
catch(Exception ex)
![]()
![]()
![]()
{
![]()
ex.printStackTrace();
![]()
}
![]()
![]()
try
![]()
![]()
![]()
{
![]()
if(fOut != null)
![]()
![]()
![]()
{
![]()
fOut.close();
![]()
}
![]()
}
![]()
catch(Exception ex)
![]()
![]()
![]()
{
![]()
ex.printStackTrace();
![]()
}
![]()
![]()
try
![]()
![]()
![]()
{
![]()
if(in != null && !justStream)
![]()
![]()
![]()
{
![]()
in.close();
![]()
}
![]()
![]()
if(fIn != null)
![]()
![]()
![]()
{
![]()
fIn.close();
![]()
}
![]()
}
![]()
catch(Exception ex)
![]()
![]()
![]()
{
![]()
ex.printStackTrace();
![]()
}
![]()
}
![]()
![]()
try
![]()
![]()
![]()
{
![]()
sock.close();
![]()
}
![]()
catch(Exception ex)
![]()
![]()
![]()
{
![]()
debug(ex.toString());
![]()
}
![]()
![]()
if(!Settings.getFtpPasvMode())
![]()
![]()
![]()
{
![]()
try
![]()
![]()
![]()
{
![]()
ssock.close();
![]()
}
![]()
catch(Exception ex)
![]()
![]()
![]()
{
![]()
debug(ex.toString());
![]()
}
![]()
}
![]()
![]()
finished = true;
![]()
![]()
if(ok)
![]()
![]()
![]()
{
![]()
con.fireProgressUpdate(file, FINISHED, -1);
![]()
}
![]()
else
![]()
![]()
![]()
{
![]()
con.fireProgressUpdate(file, FAILED, -1);
![]()
}
![]()
}
![]()
待续
......
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/20282/showart_1010985.html |
|