一.多线程下载
多线程同时操作一个文件
1.首先得知道文件有多大, getContentLengthLong()
2.然后根据线程数分出每一个小块,然后计算出每个小块应该从什么地方下载到什么地方,为了保证数据的完整性,最后一个线程下载剩余所有的字节。
3.通过RandomAcessFile来创建一个可读可写的空白文件,并且设置length为文件的大小,这样就创建了一个XXX大小的空白文件
4.将每个线程应该现在的起点和终点已经文件地址传给下载线程,由下载线程去发起下载,
5.中间需要设置一个请求头,”range”,”bytes=起点-(终点-1)”,如果服务端接受,就会返回206,然后在里面再通过RandomAcessFile来访问原始创建的文件,然后调用seek方法,将偏移量设置为当前线程的下载起点值,然后开始写流,写完OK
setRequestProperty(“range”, “bytes=” + startbyte + “-” + (endbyte - 1))
randomAccessFile.seek(startBytes);
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
/**
* Created by Administrator on 2016/7/26.
*/
public class MultiThreadDownLoadFileDemo {
private static final String REQUESTFILEPATH = "http://localhost:8080/day14servletdemo/baidu.exe";
public static void main(String[] args) {
downLoadFile(REQUESTFILEPATH);
}
/**
* 多线程下载文件
*/
private static void downLoadFile(String requestPath) {
//首先的知道文件有多大
try {
URL url = new URL(requestPath);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setConnectTimeout(5000);
httpURLConnection.setReadTimeout(5000);
httpURLConnection.connect();
if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
//返回数据了,可以获取文件大小
long lenght = httpURLConnection.getContentLengthLong();//获取文件的长度
//创建一个和目标文件一样大的空白文件
RandomAccessFile randomAccessFile = new RandomAccessFile("d:/2222.exe", "rw");
randomAccessFile.setLength(lenght);//设置文件大小
//根据线程数分块
int threadCount = 5;
long blockSize = lenght / 5;//每个线程应该下载多少
long endbyte;//结束的点
System.out.println("总长度" + lenght);
//计算每个线程应该从什么地方下载到什么地方
for (int i = 0; i < threadCount; i++) {
// i*blockSize i*blockSize+blockSize
if (i == threadCount - 1) {
System.out.println("起点" + (i * blockSize) + "结束" + lenght);
endbyte = lenght;//当是最后一个线程的时候应该下载剩余的所有的字节
} else {
System.out.println("起点" + (i * blockSize) + "结束" + (i * blockSize + blockSize));
endbyte = i * blockSize + blockSize;//不是最后一个线程
}
MyDownLoadThread myDownLoadThread = new MyDownLoadThread(i * blockSize, endbyte, requestPath);//创建下载线程
myDownLoadThread.start();
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
多线程下载
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
public class MyDownLoadThread extends Thread {
private long startbyte, endbyte;//定义每个线程下载的起始和结束位置
private String filePath;//文件的下载地址
private long progess;//当前线程的下载进度
public MyDownLoadThread(long startbyte, long endbyte, String filePath) {
this.startbyte = startbyte;
this.endbyte = endbyte;
this.filePath = filePath;
this.progess = startbyte;
}
@Override
public void run() {
try {
System.out.println(Thread.currentThread().getName() + "开始下载了");
URL url = new URL(filePath);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setConnectTimeout(5000);
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setReadTimeout(5000);
//设置请求头,规定请求数据的范围
httpURLConnection.setRequestProperty("range", "bytes=" + startbyte + "-" + (endbyte - 1));
httpURLConnection.connect();
if (httpURLConnection.getResponseCode() == HttpURLConnection.HTTP_PARTIAL) {//服务端接受我们的分段现在请求 并且返回数据
//写文件
RandomAccessFile randomAccessFile = new RandomAccessFile("d:/2222.exe", "rw");//使用随机读写流访问当前下载的文件
//
randomAccessFile.seek(startbyte);//设置偏移量,从什么地方开始写流
InputStream in = httpURLConnection.getInputStream();
int len = 0;
byte[] bs = new byte[1024 * 8];
while ((len = in.read(bs)) != -1) {
System.out.println(Thread.currentThread().getName() + "已经下载了" + (progess += len));
randomAccessFile.write(bs, 0, len);
}
randomAccessFile.close();
in.close();
System.out.println(Thread.currentThread().getName() + "下载结束");
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}