日期:2014-05-20  浏览次数:20643 次

j2EE如何实现文件的断点续传
我想做一个能支持断点续传的上传下载功能,不过听说struts2不能实现断点续传,还请各位高手来指点指点,如果有代码最好给我贴出代码,本来我不喜欢让别人给源码的,不过这次做了比较久,所以不懂得地方很多,还请各位能为小弟解决这个问题。

------解决方案--------------------
这是我做的android上的代码,希望对你有帮助:
1>首先得到下载文件的长度,然后设置本地文件的长度。
HttpURLConnection.getContentLength();
RandomAccessFile file = new RandomAccessFile("QQWubiSetup.exe","rwd");
file.setLength(filesize);//设置本地文件的长度与要下载文件的长度是相等的
2>根据文件长度和线程数计算每条线程下载的数据长度和下载位置。如:文件的长度为6M,线程数为3,那么,每条线程下载的数据长度为2M,每条线程开始下载的位置如上图所示。
3>使用Http的Range头字段指定每条线程从文件的什么位置开始下载,下载到什么位置为止,如:指定从文件的2M位置开始下载,下载到位置(4M-1byte)为止,代码如下:
HttpURLConnection.setRequestProperty("Range", "bytes=2097152-4194303");
4>保存文件,使用RandomAccessFile类指定每条线程从本地文件的什么位置开始写入数据。
RandomAccessFile threadfile = new RandomAccessFile("QQWubiSetup.exe ","rwd");
threadfile.seek(2097152);//从文件的什么位置开始写入数据
而如果上面的不能被整除,例如10个字节分3个线程的话,那么前两个线程下载4个字节,最后一个线程下载2个字节。
每条线程下载的数据长度为:文件的总大小%线程数==0?文件的总大小/线程数:文件的总大小/线程数+1
计算某条线程应该从文件的什么位置开始下载到什么位置结束:
开始位置公式:n*length;
结束为位置公式:(n+1)*length-1(n为表示线程的索引值第一个为0,length为每条线程下载的长度);

public class FileDownLoader {
@Test
public void download() throws Exception {
String path = "http://net.itcast.cn/QQWubiSetup.exe";
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5*1000);
conn.setRequestMethod("GET");
conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Charset", "UTF-8");
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
conn.setRequestProperty("Connection", "Keep-Alive");
System.out.println(conn.getResponseCode());

int filesize = conn.getContentLength();//得到文件大小
conn.disconnect();
int threasize = 3;//线程数
int perthreadsize = filesize / 3 + 1;
RandomAccessFile file = new RandomAccessFile("102.wma","rw");
file.setLength(filesize);//设置本地文件的大小
file.close();
for(int i=0; i<threasize ; i++){
int startpos = i * perthreadsize;//计算每条线程的下载位置
RandomAccessFile perthreadfile = new RandomAccessFile("102.wma","rw");//
perthreadfile.seek(startpos);//从文件的什么位置开始写入数据
new DownladerThread(i, path, startpos, perthreadsize, perthreadfile).start();
}
//以下代码要求用户输入q才会退出测试方法,如果没有下面代码,会因为进程结束而导致进程内的下载线程被销毁
int quit = System.in.read();
while('q'!=quit){
Thread.sleep(2 * 1000);
}
}

private class DownladerThread extends Thread{
private int startpos;//从文件的什么位置开始下载
private int perthreadsize;//每条线程需要下载的文件大小
private String path;
private RandomAccessFile file;
private int threadid;

public DownladerThread(int threadid, String path, int startpos, int perthreadsize, RandomAccessFile perthreadfile) {
this.path = path;
this.startpos = startpos;
this.perthreadsize = perthreadsize;
this.file = perthreadfile;
this.threadid = threadid;
}

@Override
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setConnectTimeout(5 * 1000);
conn.setRequestMethod("GET");