首先来说说原理吧,既然是下载文件,那肯定需要知道文件的长度了,所以在下载网络文件之前,先调用httpURLConnection的一个方法getContentLength()来获取到文件长度,然后根据文件长度设置每条线程负责下载的数据量,当然,线程数量由你自己来决定。还是上代码直观点。
package download;
import java.io.File;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* 多线程下载网络文件
*
* @author xgp
*
*/
public class MultipleThreadsDownload {
public static void main(String[] args) {
String path = "http://10.19.160.53/web/test.txt";
new MultipleThreadsDownload().down(path, 3);// 分为3条线程来下载文件
}
private void down(String path, int threadSize) {
try {
URL url = new URL(path);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setConnectTimeout(5000);
con.setRequestMethod("GET");
//当服务器没有开启,请求会失败,响应码是得不到的,故会抛出异常
if (con.getResponseCode() == 200) {
// 请求成功
int length = con.getContentLength();// 获取文件长度
File file = new File(getFileName(path));
// System.out.println(getFileName(path));
RandomAccessFile access = new RandomAccessFile(file, "rwd");
access.setLength(length);// 设置读取的文件和网络文件的长度相同
access.close();
// 计算每条线程负责下载的数据量,若文件长度整除线程数,返回下载量,若不能整除,则+1条下载量
int block = length % threadSize == 0 ? length % threadSize
: length % threadSize + 1;
for (int threadid = 0; threadid < threadSize; threadid++) {
new DownloadThread(threadid, file, block, url).start();
}
} else {
System.out.println("请求失败");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 取得文件名称
*
* @param path
* @return
*/
private String getFileName(String path) {
return path.substring(path.lastIndexOf("/")+1);
}
class DownloadThread extends Thread {
private int threadid;
private File file;
private int block;
private URL url;
public DownloadThread(int threadid, File file, int block, URL url) {
this.threadid = threadid;
this.file = file;
this.block = block;
this.url = url;
}
@Override
public void run() {
super.run();
int start = threadid * block;// 计算线程最开始下载文件的位置
int end = (threadid + 1) * block - 1;// 下载结束位置
RandomAccessFile access;
try {
access = new RandomAccessFile(file, "rwd");
access.seek(start);// 在该位置发生下一个读取或写入操作
HttpURLConnection con = (HttpURLConnection) url
.openConnection();
con.setConnectTimeout(5000);
con.setRequestMethod("GET");
con.setRequestProperty("Range", "byte=" + start + "-" + end);// 分段下载任务
if (con.getResponseCode() == 200) {
InputStream is = con.getInputStream();
byte[] buf = new byte[1024];
int line = 0;
while ((line = is.read(buf)) != -1) {
access.write(buf, 0, line);
}
is.close();
}
access.close();
System.out.println("线程" + (threadid + 1) + "下载完成!");
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
这里只是java的调用代码,如果想用到andoird中结合progressbar一起使用则需要注意设置progressbar的一些相关参数,还要注意线程异步