多线程下载,我们主要使用到HttpURLConnection、线程、RandomAccessFile这几部分的知识。普通的下载和多线程下载,就像多个水管和一个水管抽水一样,多个管子同时运作,效率自然比一个管子快的多,但受限于水管的粗细,所以水流量也不会太夸张。
话不多说,直接上代码:
package org.testDt;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* @author jzw
*/
public class TestRandomDown {
public void multiDown(final String sourcePath,String savePath,int threadNum) {
final File file = new File(savePath);
try {
URL url = new URL(sourcePath);
HttpURLConnection huc = (HttpURLConnection) url.openConnection();
//获取响应码和文件大小
int responseCode = huc.getResponseCode();
final int fileSize = huc.getContentLength();
huc.disconnect();
//给线程划分下载块
int blockSize = (fileSize + threadNum - 1)/threadNum;
if (responseCode == 200) {
for (int i = 0;i < threadNum;i++) {
final int a = i;
final int start = blockSize * a;// 开始位置
final int end = blockSize * (a + 1) - 1;// 结束位置
//每个线程使用一个RandomAccessFile进行下载
new Thread(new Runnable() {
@Override
public void run() {
try {
URL url = new URL(sourcePath);
HttpURLConnection huc1 = (HttpURLConnection) url.openConnection();
//设置请求返回的文件大小范围
huc1.setRequestProperty("Range", "bytes="+start+"-"+end+"");
InputStream in = huc1.getInputStream();
/*
* 创建一个存储资源文件对应的虚拟文件,该文件可用来随机访问文件的读取和写入
* "rwd",打开以便读取和写入,保证由该调用对此文件所做的所有更改均被写入底层存储设备中
*/
RandomAccessFile acf = new RandomAccessFile(file,"rwd");
//设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作
//在这里file中最后就存储了所有线程下载的文件
acf.seek(start);
byte[] buffer = new byte[1024];
int len = 0;
while((len=in.read(buffer)) != -1) {
acf.write(buffer, 0, len);
}
System.out.println("线程:" + a + "下载完成!");
acf.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}).start();
}
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
TestRandomDown t= new TestRandomDown();
t.multiDown("http://forum.csdn.net/PointForum/ui/scripts/csdn/Plugin/003/monkey/20.gif",
"D://testXiaZai/20.gif", 3);
}
}
至于断点下载,无非是用配置文件或变量记录下文件的下载进度,即每个线程下载到了哪个字节数,等重新开始下载时,在该位置的下一个字节数继续下载即可。