您的位置:首页 > 移动开发 > Android开发

java(android)多线程下载,和多线程断点下载

2015-06-07 21:12 351 查看
多线程(断点)下载要点:

1:计算出每个线程要下载的大小 ,下载的起始位置和结束位置

2:设置请求头,请求服务器下载文件的哪部分 conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);

3:创建一个与服务器大小一样的随机读写文件 RandomAccessFile file = new RandomAccessFile("文件名", "rw");

(断点)

4:每读写一段数据记录一次下载位置

5:重新开始下载时,要从保存的配置文件中读取下载位置

一:多线程下载Demo

import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

/**
* 多线程下载
*/
public class MultiTheadDownload {

// 开启的线程数,默认是3个线程啊。
private static int theandCount = 3;

public static void main(String[] args) throws Exception {

String path = "http://10.0.177.167:8080/360.exe";// 访问网址
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(5000);
conn.setRequestMethod("GET");

int code = conn.getResponseCode();
if (code == 200) {

// 得到文件的大小
int length = conn.getContentLength();
// 计算出每个线程要下载的大小。后面不能整除的留给最后一个线程。
int blockSize = length / theandCount;

// System.out.println();

// 创建一个与服务器大小一样的随机读写文件
RandomAccessFile file = new RandomAccessFile("360.exe", "rw");
file.setLength(length);// 设置生成的随机文件的大小
file.close();

for (int theandId = 1; theandId <= theandCount; theandId++) {

// 求出线程开始下载的位置 :(线程号-1)*每个线程下载的大小。
int startIndex = (theandId - 1) * blockSize;
// 求出线程结束下载的位置: 线程号*每个线程下载的大小-1
int endIndex = theandId * blockSize - 1;

if (theandId == theandCount) {
endIndex = length;
}

System.out.println("线程" + theandId + "下载" + startIndex + "---->" + endIndex);

// 开启线程
new DownloadTheand(startIndex, endIndex, theandId, path).start();
}

} else {
System.out.println("连接失败");
}

}

/**
* 每个线程处理类
*/
public static class DownloadTheand extends Thread {

private int startIndex;// 文件的开始位置
private int endIndex;// 文件的结束位置
private String path;// 下载URL
private int threadId;// 线程id

/**
*
* @param startIndex
*            文件的开始位置
* @param endIndex
*            文件的结束位置
* @param filePath
*            下载URL
*/
public DownloadTheand(int startIndex, int endIndex, int threadId, String path) {
this.startIndex = startIndex;
this.endIndex = endIndex;
this.path = path;
this.threadId = threadId;
}

public void run() {

try {

URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(5000);
conn.setRequestMethod("GET");
// 设置请求头,请求服务器下载文件的哪部分
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
// 从服务器返回全部资源200 ok,如果从服务器请求部分资源 206 ok
int code = conn.getResponseCode();
System.out.println(code);
InputStream in = conn.getInputStream();// 返回从startIndex开始的部分文件的流

// 开启随机文件读取流
RandomAccessFile raf = new RandomAccessFile("360.exe", "rw");
raf.seek(startIndex);// 设置随机文件从哪里开启读写

int len = 0;
byte[] buffe = new byte[1024];
while ((len = in.read(buffe)) != -1) {
raf.write(buffe, 0, len);

}
in.close();
raf.close();

System.out.println("当前线程" + threadId + "下载完成");

} catch (Exception e) {
e.printStackTrace();
System.out.println("当前线程" + threadId + "下载成败");
}

}
}

}
二;多线程断点下载Demo

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

/**
* 多线程断点下载
*/

public class MultiTheadBreakpointDownload {

/**开启的线程总数**/
public static int threadCount = 3;

/**正在运行的线程数**/
public static int runningThread = 3;

public static void main(String[] args) throws Exception {
// 1.连接服务器 , 获取一个文件, 获取文件的长度, 在本地创建一个大小跟服务器文件一样大的临时文件
String path = "http://10.0.177.167:8080/360.exe";
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
int code = conn.getResponseCode();
if (code == 200) {
// 服务器返回的数据的长度 实际上就是文件的长度
int length = conn.getContentLength();
System.out.println("文件总长度:" + length);
// 在客户端本地 创建出来一个大小跟服务器端文件一样大小的临时文件
RandomAccessFile raf = new RandomAccessFile("setup.exe", "rw");
// 指定创建的这个文件的长度
raf.setLength(length);
raf.close();

// 假设是3个线程去下载资源.
// 平均每一个线程下载的文件的大小.
int blockSize = length / threadCount;
for (int threadId = 1; threadId <= threadCount; threadId++) {
// 第一个线程下载的开始位置
int startIndex = (threadId - 1) * blockSize;
int endIndex = threadId * blockSize - 1;
if (threadId == threadCount) {// 最后一个线程 下载的长度 要稍微长一点
endIndex = length;
}
System.out.println("线程:" + threadId + "下载:---" + startIndex + "--->" + endIndex);
new DownloadThread(path, threadId, startIndex, endIndex).start();
}

} else {
System.out.println("服务器错误.");
}
}

/**
* 下载文件的子线程 每一个线程 下载对应位置的文件
*
* @author Administrator
*
*/
public static class DownloadThread extends Thread {
private int threadId;//线程id
private int startIndex;//线程下载的开始位置
private int endIndex;// 线程下载的结束位置.
private String path;//下载URL

/**
* @param path
*            下载URL
* @param threadId
*            线程id
* @param startIndex
*            线程下载的开始位置
* @param endIndex
*            线程下载的结束位置.
*/
public DownloadThread(String path, int threadId, int startIndex, int endIndex) {
this.threadId = threadId;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.path = path;
}

@Override
public void run() {
try {

// 检查是否存在 记录下载长度的文件 ,如果存在读取这个文件的数据.
File tempFile = new File(threadId + ".txt");
if (tempFile.exists() && tempFile.length() > 0) {
FileInputStream fis = new FileInputStream(tempFile);
byte[] temp = new byte[1024];
int leng = fis.read(temp);
String downloadLen = new String(temp, 0, leng);
int downloadlenInt = Integer.parseInt(downloadLen);
startIndex = downloadlenInt;// 修改下载的真实的开始位置.
fis.close();
}

URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
// 重要: 请求服务器下载部分的文件 指定文件的位置.
conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
System.out.println("线程真实下载:" + threadId + "下载:---" + startIndex + "--->" + endIndex);
conn.setConnectTimeout(5000);
int code = conn.getResponseCode(); // 从服务器请求全部资源 200 ok
// 如果从服务器请求部分资源 206 ok
if (code == 206) {
InputStream is = conn.getInputStream();// 已经设置了 请求的位置
RandomAccessFile raf = new RandomAccessFile("setup.exe", "rw");
// 随机写文件的时候 从哪个位置开始写
raf.seek(startIndex);// 定位文件
int len = 0;
byte[] buffer = new byte[1024];
int total = 0;// 已经下载的数据长度
while ((len = is.read(buffer)) != -1) {
RandomAccessFile file = new RandomAccessFile(threadId + ".txt", "rw");// 作用:记录当前线程下载的数据长度
raf.write(buffer, 0, len);
total += len;
// System.out.println("线程:" + threadId + "total:" +
// total);
file.write((total + startIndex + "").getBytes());// 记录的是下载位置.
file.close();
}
is.close();
raf.close();
System.out.println("线程:" + threadId + "下载完毕了...");
} else {
System.out.println("线程:" + threadId + "下载失败...");
}

File deleteFile = new File(threadId + ".txt");
deleteFile.delete();// 当线程下载完毕后 清楚掉 下载的记录

// 如何去判断应用程序已经下载完毕.

} catch (Exception e) {
e.printStackTrace();
} finally {
runningThread--;

if (runningThread == 0) {// 所有的线程 已经执行完毕了.
for (int i = 1; i <= 3; i++) {
File file = new File(i + ".txt");
file.delete();
}
System.out.println("文件下载完毕 ,删除所有的下载记录.");
}
}

}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: