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

多线程下载

2016-06-24 13:48 323 查看
多线程下载的实现:

1、首先获取文件的长度。

2、设置线程的个数

3、根据长度和线程个数计算每一个线程需要下载的长度。

例如:3个线程下载一个为length=10个字节的文件

int bolckSize=length/3;

则每一部分需要下载的大小为:

线程  1   :int start=0*blockSize     int end=1*blockSize-1;

线程  2   :int start=1*blockSize     int end=2*blockSize-1;

线程  3   :int start=2*blockSize     int end=length-1;//到最后

4、根据RandomAccessFile  raf 创建一个同样大小的空文件。

5、设置Http请求的头信息

connection.setRequestProperty("range", "bytes=" + start + "-" + end);


6、根据raf.seek(int length),把下载好的数据写入空文件的指定位置,拼接成完整的文件。

实现:

用Tomcat作为服务器,服务器目录C:\Program Files\Apache Software Foundation\Tomcat 7.0\webapps\ROOT下放置了一个guanguan.apk文件。

主界面就一个Button按钮。

public class MainActivity extends Activity implements View.OnClickListener {
//    要下载文件的路径
private String urlPath = "http://localhost:8080/guanguan.apk";
private String filePath;
//    设置线程的数目。
private int threadCount = 3;
private Button mButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button) findViewById(R.id.button);
mButton.setOnClickListener(this);
}

@Override
public void onClick(View view) {
if (view.getId() == R.id.button) {
Log.d("dd","开始下载");
new Thread(new GetDataFromNet()).start();
}
}
//访问网络的类:
private class GetDataFromNet implements Runnable {
@Override
public void run() {
try {

//请求网络
URL url = new URL(urlPath);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);
//  获取返回值
int code = connection.getResponseCode();
if (code == 200) {
// 获取数据总长度
int length = connection.getContentLength();
Log.d("dd","文件长度"+length);
//  设置下载位置
filePath = "/sdcard" + "/guanguan.apk";
File file = new File(filePath);
Log.d("dd", "下载路径:" + filePath);

//    通过RandomAccessFile创建一个空文件。   rwd  文件权限信息
RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
//     设置空文件的大小
accessFile.setLength(length);
accessFile.close();

//每一段的大小
int bolckSize = length / threadCount;

//计算每个线程下载的起始位置。
for(int i = 0; i < threadCount; i++) {
int start = i * bolckSize;
int end = (i + 1) * bolckSize - 1;

//如果是最后一个线程,则结束位置为文件的末尾
if (i == (threadCount - 1)) {
end = length-1;
}
Log.d("dd", "第" + i + "个线程" + "从" + start + "到" + end);
new DownloadFile(urlPath, filePath, start, end).start();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}

//文件下载类
public class DownloadFile extends Thread {
private String urlPath;//下载路径
private String fileName;//文件保存路径
private int start;//开始位置
private int end;//结束位置
//构造方法
public DownloadFile(String urlPath, String fileName, int start, int end) {
this.urlPath = urlPath;
this.fileName = fileName;
this.start = start;
this.end = end;
}
@Override
public void run() {
URL url = null;
try {
url = new URL(urlPath);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("GET");
connection.setConnectTimeout(5000);

//   设置Http头的信息,即要指明获取的是那一段数据。

connection.setRequestProperty("range", "bytes=" + start + "-" + end);

int code = connection.getResponseCode();

//注意部分下载返回的code值为  206
if (code == 206) {
InputStream is = connection.getInputStream();
File file = new File(fileName);

//创建RandomAccessFile,要与上次已经创建文件名以及权限一致
RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");

//该方法用来操作建造好的空文件,可以指明从文件的那个位置开始写入
accessFile.seek(start);
byte[] buf = new byte[1024];
int len = 0;
while ((len = is.read(buf)) >0) {
accessFile.write(buf, 0, len);
}
is.close();
accessFile.close();
Log.d("dd", "该线程下载了" + start + "--" + end);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}

运行结果:

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