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

文件的下载和断电续传

2016-02-07 16:26 573 查看
[1]文件的分块

[2]断点的保存

使用RandomAccessFile 类,不停留在缓冲区,而是直接写进外存

RandomAccessFile raff=new RandomAccessFile(getFileName(path)+threadId+".txt", "rwd");


[3]删除断点文件是使用互斥访问

//互斥访问
synchronized (DownLoadThread.class) {
runingThread--;
if (runingThread==0) {
for (int i = 0; i < threadCount; i++) {
File deleteFile=new File(getFileName(path)+i+".txt");
deleteFile.delete();
}
}


package jacky.mutildownload;

import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInput
4000
Stream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

private EditText ed_downloadurl;
private EditText ed_threadcount;
private LinearLayout ll_pb;
private String path;
private int threadCount;
private  int runingThread = 0;
private List<ProgressBar> pbLists;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//找到我们的控件
ed_downloadurl = (EditText) findViewById(R.id.ed_downloadurl);
ed_threadcount = (EditText) findViewById(R.id.ed_threadcount);
ll_pb = (LinearLayout) findViewById(R.id.ll_pb);

//添加进度条引用
pbLists = new ArrayList<ProgressBar>();
}
//下载
public void click(View v) {
//获取url 和 线程数量
path = ed_downloadurl.getText().toString().trim();
threadCount = Integer.parseInt(ed_threadcount.getText().toString().trim());
//先移除所有进度条,再进行进度条增加
ll_pb.removeAllViews();
pbLists.clear();
for (int i=0;i<threadCount;i++){
//打气筒
ProgressBar pbView=(ProgressBar)View.inflate(getApplicationContext(),R.layout.item,null);

//把pbView添加到集合中
pbLists.add(pbView);

//动态添加一个进度条
ll_pb.addView(pbView);
}
//进行下载的逻辑
new Thread(){
@Override
public void run() {
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setReadTimeout(5000);
conn.setRequestMethod("GET");
int code = conn.getResponseCode();
if (code == 200) {

//把线程数量赋值给正在运行的线程

runingThread= threadCount;

int length = conn.getContentLength();
// 计算出每个线程下载的大小
int blockSize = length / threadCount;

// 计算每个线程下载的开始和结束位置
for (int i = 0; i < threadCount; i++) {
int startIndex = i * blockSize;
int endIndex = (i + 1) * blockSize - 1;
// 如果为最后一个线程,则多下载些,下载到结尾
if (i == threadCount - 1) {
endIndex = length - 1;
}

System.out.println("线程id:"+i+"理论下载位置"+startIndex+"---"+endIndex);

// 创建线程
DownLoadThread downLoadThread = new DownLoadThread(
startIndex, endIndex, i);
downLoadThread.start();
}

}
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();

}

private class DownLoadThread extends Thread {
private int startIndex;
private int endIndex;
private int threadId;
private int pbMaxSize;//进度条的最大值
private int pblastPostion=0;//上次下载重点的位置

public DownLoadThread(int startIndex, int endIndex, int threadId) {
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
}

@Override
public void run() {
try {
pbMaxSize=endIndex-startIndex;
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setReadTimeout(8000);
conn.setRequestMethod("GET");

//读取断点。
//TODO
File file=new File(getFileName(path)+threadId+".txt");
if (file.exists()&&file.length()>0) {
FileInputStream fis = new FileInputStream(file);
BufferedReader bufr=new BufferedReader(new InputStreamReader(fis));
String lastpostionn=bufr.readLine();
int lastpostion = Integer.parseInt(lastpostionn);
//创建进度条的开始位置
pblastPostion=lastpostion-startIndex;
//改变一下开始位置
startIndex=lastpostion+1;
System.out.println("线程id:"+threadId+"真是下载位置"+startIndex+"---"+endIndex);
//关闭流
fis.close();
}

// 设置一个请求头
conn.setRequestProperty("Range", "bytes=" + startIndex + "-"
+ endIndex);

int code = conn.getResponseCode();
// 200请求全部资源成功 206请求部分资源成功
if (code == 206) {
// 创建随机读写对象
RandomAccessFile raf = new RandomAccessFile(getFileName(path),
"rw");
// 设置开始写的位置
raf.seek(startIndex);
InputStream in = conn.getInputStream();

// 写数据到文件中
int len = -1;
//设置缓冲区为5M
byte[] buffer = new byte[1024*1024*5];
int total = 0;//代表当前线程下载的大小
while ((len = in.read(buffer)) != -1) {
raf.write(buffer, 0, len);
total+=len;
//将实现断点续传的位置存起来,存到一个.txt中
int currentThreadPosition=startIndex+total;
RandomAccessFile raff=new RandomAccessFile(getFileName(path)+threadId+".txt", "rwd");
raff.write(String.valueOf(currentThreadPosition).getBytes());
raff.close();

//设置进度条的最大长度
pbLists.get(threadId).setMax(pbMaxSize);
//设置进度条的当前位置
pbLists.get(threadId).setProgress(pblastPostion+total);
}
raf.close();

System.out.println("线程id:" + threadId + "下载完成");
//互斥访问
synchronized (DownLoadThread.class) {
runingThread--;
if (runingThread==0) {
for (int i = 0; i < threadCount; i++) {
File deleteFile=new File(getFileName(path)+i+".txt");
deleteFile.delete();
}
}

}
}
} catch (Exception e) {
e.printStackTrace();
}
}

};

public String getFileName(String path) {
int start=path.lastIndexOf("/")+1;
//写到SD卡
String pathName= Environment.getExternalStorageDirectory().getPath()+"/"+path.substring(start);
return pathName;

}
}






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