Chinaunix首页 | 论坛 | 博客
  • 博客访问: 415408
  • 博文数量: 112
  • 博客积分: 4000
  • 博客等级: 上校
  • 技术积分: 905
  • 用 户 组: 普通用户
  • 注册时间: 2006-06-05 21:14
文章分类

全部博文(112)

文章存档

2009年(3)

2008年(24)

2007年(55)

2006年(30)

我的朋友

分类: Java

2008-06-25 12:40:43

五、断点续传

对于熟用QQ的程序员,QQ的断点续传功能应该是印象很深刻的。因为它很实用也很方面。因此,在我们的上传下载过程中,很实现了断点续传的功能。

其实断点续传的原理很简单,就在上传的过程中,先去服务上进行查找,是否存在此文件,如果存在些文件,则比较服务器上文件的大小与本地文件的大小,如果服务器上的文件比本地的要小,则认为此文件上传过程中应该可以进行断点续传。

在实现的过程中,RandomAccessFile类变得很有用。此类的实例支持对随机存取文件的读取和写入。随机存取文件的行为类似存储在文件系统中的一个大型字节数组。存在指向该隐含数组的光标或索引,称为文件指针;输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机存取文件以读取/写入模式创建,则输出操作也可用;输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法进行设置。

RandomAccessFile类的skipBytes方法尝试跳过输入的 n 个字节以丢弃跳过的字节。如果从服务器上查得待上传文件的大小n,则采用skipBytes方法可以跳过这n个字节,从而开始从新的地方开始进行断点续传。具体的方法说明可以参见JDK5API说明。

可以在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);
        }

    }


待续
......
阅读(2055) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~