ThreadId:0,1,2
int block = 4; 每个线程下载的数据量
int start = ThreadId * block; 每个线程下载的起始位置
0*4 = 0 0开始下载
1*4 = 4 4开始下载
2*4 = 8 8开始下载
int end = (ThreadId+1) * block -1;
(0+1)*4-1 = 3 3是线程0下载结束位置
(1+1)*4-1 = 7 7是线程1下载结束位置
conn.getContentLength(); 获取要下载文件的大小API
随机访问文件类RandomAccessFile(File file,String mode)
文件包含两部分:元数据(日期,作者,等),数据
mode:推荐rwd
r :只读方式
rw :读写方式
rws:要求对文件的内容-元数据每个更新都同步到存储设备
rwd:要求对文件的内容的每个更新同步到存储设备(每次更新不包含元数据)
DownloadThread.java
package netdown;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
/**
* threadId:开启的每条线程的id
* block:每条线程下载的数据量
* url :下载原地址
* file :要保存的本地文件
* run() 执行下载
* conn.setRequestMethod("GET")
* conn.setRequestProperty(Range:范围,开始位置-结束位置)
* InputStream inStream = conn.getInputStream(); 从conn获得 输入流
* inStream.read();
*/
public class DownloadThread extends Thread{
int threadId;
int block;
URL url;
File file;
public DownloadThread(int threadId, int block, URL url, File file) {
this.threadId = threadId;
this.block = block;
this.url = url;
this.file = file;
}
public void run() {
int start = threadId * block;//每条线程开始下载位置
int end = (threadId+1) * block -1;//每条线程结束下载位置
//线程数据写入
try {
RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
accessFile.seek(start);//文件指针指向start位置开始写入
//发起请求
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
conn.setRequestProperty("Range", "bytes="+start+"-"+end);
//分段下载请求码是206
if(conn.getResponseCode() == 206){
System.out.println(conn.getResponseCode());
//从conn获得 输入流
InputStream inStream = conn.getInputStream();
byte[] buffer = new byte[1024];//缓冲区
int len = 0;//起始0 --- 缓冲区读取结束
while( (len = inStream.read(buffer)) != -1){
accessFile.write(buffer, 0, len);//buffer 写入 文件
}
accessFile.close();
inStream.close();
}
System.out.println("Thread:"+(threadId+1)+"下载完成!");
} catch (Exception e) {
e.printStackTrace();
}
super.run();
}
}
MultThreadDownload.java //多线程下载
package netdown;
import java.io.File;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
public class MultThreadDownload {
public static void main(String[] args) {
String path = "http://192.168.1.4:8080/apache-tomcat-8.0.11-windows-i64.zip";
new MultThreadDownload().download(path,3);
}
/**
* 下载文件 内部方法
* @param path 网络文件路径
* @param ThreadCount 开启几条线程
* DownloadThread 创建的线程calss
*/
private void download(String path,int ThreadCount) {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if(conn.getResponseCode() == 200){
//API获取服务器返回下载的文件的大小,getContentLength();
int length = conn.getContentLength();
//本地生成与网络文件相同大小的文件
File file = new File(getFilename(path));
RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
accessFile.setLength(length);//本地生成文件
accessFile.close();
//计算每条线程下载的数据量
int block = length%ThreadCount == 0 ? length/ThreadCount : length/ThreadCount+1;
for (int ThreadId = 0; ThreadId < ThreadCount; ThreadId++) {
new DownloadThread(ThreadId,block,url,file).start();
}
}else{
System.out.println("下载失败!");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @param path 全路径
* @return path 下载文件名称(过滤掉http地址,取得下载文件名称)
*/
private String getFilename(String path) {
return path.substring(path.lastIndexOf("/")+1);
}
}