技术开发 频道

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



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

【IT168 专稿】

五、断点续传
对于熟用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); } }
0
相关文章