多线程下载文件
DownThread类是一ige下载线程,该线程在启动的时候需要指定下载文件的URL、下载起始点和下载结束点等参数。下载过程中利用RandomAccessFile类将下载的内容写入目标文件,通过RandomAccessFile类的seek()方法可以指定写入目标文件的其实位置。DownThread类的实现代码如下:
package com.hover.net;
import java.io.BufferedInputStream;
import java.io.File;
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 <a href="mailto:gaoxiang114@163.com">高祥</a>
* @version 1.0.0.2014年4月9日
*/
public class DownThread implements Runnable{
private String url = "";
private File file;
private long startIndex;
private long endIndex;
public DownThread(String url, File file, long startIndex, long endIndex) {
this.url = url;
this.file = file;
this.startIndex = startIndex;
this.endIndex = endIndex;
}
@Override
public void run() {
try {
URL downUrl = new URL(url);
HttpURLConnection connect = (HttpURLConnection)downUrl.openConnection();
connect.setRequestProperty("User-Agent", "NetFox");
String sProperty = "bytes="+startIndex+"-";
if(endIndex > 0){
sProperty = "bytes="+startIndex+"-"+endIndex;
}
connect.setRequestProperty("RANGE", sProperty);
System.out.println(sProperty);
//利用RandomAccessFile
RandomAccessFile dst = new RandomAccessFile(file,"rw");
//从startIndex字节的位置开始写入信息
dst.seek(startIndex);
InputStream is = connect.getInputStream();
BufferedInputStream br = new BufferedInputStream(is);
byte[] buf = new byte[1024];
long size = -1;
while((size = br.read(buf))!= -1){
dst.write(buf,0,(int)size);
}
dst.close();
br.close();
connect.disconnect();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("the thread is over ! ");
}
}
MUltiDownload类主要功能是获取下载文件的大小,并根据指定的线程数量计算出每一个线程应该下载的起始点和结束点,然后创建并启动线程。MultiDownload类的实现代码如下:
package com.hover.net;
import java.io.File;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* @author <a href="mailto:gaoxiang@good10000.com">高祥</a>
* @version 1.0.0.2014年4月9日
*/
public class MultiDownload {
public static void main(String[] args) {
MultiDownload down = new MultiDownload();
try {
down.downProcess("http://www.baidu.com/img/baidu_logo.gif", "F:\\baidu_logo.gif", 4);
} catch (Exception e) {
e.printStackTrace();
}
}
public void downProcess(String url,String dest,int threadNum) throws Exception{
//获取文件大小
long fileSize = getFileLength(url);
//就算每个线程需要下载多少个字节
long bufferSize = fileSize/threadNum + 1;
File file = new File(dest);
int i = 0;
while(i<threadNum){
//计算每个线程需要下载的起始点和结束点
final long startIndex = bufferSize * i;
final long endIndex = bufferSize * (i+1);
//启动一个线程
if(i == threadNum - 1){
DownThread fileThread = new DownThread(url, file, startIndex, 0);
new Thread(fileThread).start();
}else{
DownThread fileThread = new DownThread(url, file, startIndex, endIndex);
new Thread(fileThread).start();
}
i++;
}
}
public long getFileLength(String url) throws Exception{
long size = -1;
URL downUrl = new URL(url);
HttpURLConnection connect = (HttpURLConnection) downUrl.openConnection();
int stateCode = connect.getResponseCode();
if(stateCode == 200){
size = connect.getContentLength();
connect.disconnect();
}
return size;
}
}