多线程断点下载
来源:互联网 发布:淘宝卖家打快递单 编辑:程序博客网 时间:2024/05/16 13:47
本文参考:
http://www.cnblogs.com/hanyonglu/archive/2012/02/20/2358801.html
http://blog.csdn.net/lyy1104/article/details/27227001
本示例介绍在Android平台下通过HTTP协议实现断点续传下载。
主要特点:
1.多线程下载
2.支持断点。
- 首先获得下载文件的长度,然后设置本地文件的长度。
int length=httpURLConnection.getContentLength();
- 创建本地文件+随机访问对象
File file =new File(adFile,fileName); RandomAccessFile accessFile=new RandomAccessFile(file,"rwd"); accessFile.setLength(fileLength);
- 创建多个线程+每个线程的下载任务
for(int threadId=1;threadId<threadNum;threadId++){ int startIndex=(threadId-1)*thread*size; int endIndex=threadId*threadsize-1; if(threadId==threadNum){ endIndex=fileLength-1; } }
4.保存文件,使用RandomAccessFile类指定每条线程从本地文件的什么位置开始写入数据。
RandomAccessFile threadfile = new RandomAccessFile("QQWubiSetup.exe ","rwd"); threadfile.seek(2097152);//从文件的什么位置开始写入数据
示例代码:
package com.hefei.ppa.mytest.download;import android.app.Activity;import java.io.File;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.InputStream;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;import android.os.Bundle;import android.os.Environment;import android.text.TextUtils;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.ProgressBar;import android.widget.TextView;import android.widget.Toast;import com.hefei.ppa.mytest.R;/** * Created by Administrator on 2017/1/20. */public class DownloadActivity extends Activity { // 线程开启的数量 private int threadNum = 3; private int threadRunning = 3; private EditText et_url; private ProgressBar progressBar; private TextView tv_pb; private Button bt_download; private int currentProgress; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_download); // 获取控件对象 et_url = (EditText) findViewById(R.id.et_url); progressBar = (ProgressBar) findViewById(R.id.pb_down); tv_pb = (TextView) findViewById(R.id.tv_pb); bt_download= (Button) findViewById(R.id.bt_download); File sdDir = Environment.getExternalStorageDirectory(); File pbFile = new File(sdDir,"pb.txt"); InputStream is = null; try { //判断文件是否存在 if (pbFile.exists()) { is = new FileInputStream(pbFile); } } catch (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (is != null) { String value = StreamTools.streamToStr(is); String[] arr = value.split(";"); progressBar.setMax(Integer.valueOf(arr[0]));//最大值 currentProgress = Integer.valueOf(arr[1]);//当前值 progressBar.setProgress(currentProgress); tv_pb.setText("当前的进度是:"+arr[2]);//显示百分比 } bt_download.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { downLoadFile(v); } }); } // 下载文件(得到服务器端文件的大小) public void downLoadFile(View v) { // 获取下载路径 final String spec = et_url.getText().toString(); if (TextUtils.isEmpty(spec)) { Toast.makeText(this, "下载的地址不能为空", Toast.LENGTH_LONG).show(); } else { new Thread() { public void run() { // HttpURLConnection try { // 根据下载的地址构建URL对象 URL url = new URL(spec); // 通过URL对象的openConnection()方法打开连接,返回一个连接对象 HttpURLConnection httpURLConnection = (HttpURLConnection) url .openConnection(); // 设置请求的头 httpURLConnection.setRequestMethod("GET"); httpURLConnection.setReadTimeout(5000); httpURLConnection.setConnectTimeout(5000); // 判断是否响应成功 if (httpURLConnection.getResponseCode() == 200) { // 获取下载文件的长度 int fileLength = httpURLConnection .getContentLength(); //设置进度条的最大值 progressBar.setMax(fileLength); //判断sd卡是否管用 if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) { // 保存文件 // 外部存储设备的路径 File sdFile = Environment .getExternalStorageDirectory(); //获取文件的名称 String fileName = spec.substring(spec.lastIndexOf("/")+1); //创建保存的文件 File file = new File(sdFile, fileName); //创建可以随机访问对象 RandomAccessFile accessFile = new RandomAccessFile( file, "rwd"); // 保存文件的大小 accessFile.setLength(fileLength); // 关闭 accessFile.close(); // 计算出每个线程的下载大小 int threadSize = fileLength / threadNum; // 计算出每个线程的开始位置,结束位置 for (int threadId = 1; threadId <= 3; threadId++) { int startIndex = (threadId - 1) * threadSize; int endIndex = threadId * threadSize - 1; if (threadId == threadNum) {// 最后一个线程 endIndex = fileLength - 1; } System.out.println("当前线程:" + threadId + " 开始位置:" + startIndex + " 结束位置:" + endIndex + " 线程大小:" + threadSize); // 开启线程下载 new DownLoadThread(threadId, startIndex, endIndex, spec).start(); } }else { DownloadActivity.this.runOnUiThread(new Runnable() { public void run() { Toast.makeText(DownloadActivity.this, "SD卡不管用", Toast.LENGTH_LONG).show(); } }); } }else { //在主线程中运行 DownloadActivity.this.runOnUiThread(new Runnable() { public void run() { Toast.makeText(DownloadActivity.this, "服务器端返回错误", Toast.LENGTH_LONG).show(); } }); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } }; }.start(); } } class DownLoadThread extends Thread { private int threadId; private int startIndex; private int endIndex; private String path; /** * 构造函数 * * @param threadId * 线程的序号 * @param startIndex * 线程开始位置 * @param endIndex * @param path */ public DownLoadThread(int threadId, int startIndex, int endIndex, String path) { super(); this.threadId = threadId; this.startIndex = startIndex; this.endIndex = endIndex; this.path = path; } @Override public void run() { try { File sdFile = Environment.getExternalStorageDirectory(); //获取每个线程下载的记录文件 File recordFile = new File(sdFile, threadId + ".txt"); if (recordFile.exists()) { // 读取文件的内容 InputStream is = new FileInputStream(recordFile); // 利用工具类转换 String value = StreamTools.streamToStr(is); // 获取记录的位置 int recordIndex = Integer.parseInt(value); // 将记录的位置赋给开始位置 startIndex = recordIndex; } // 通过path路径构建URL对象 URL url = new URL(path); // 通过URL对象的openConnection()方法打开连接,返回一个连接对象 HttpURLConnection httpURLConnection = (HttpURLConnection) url .openConnection(); // 设置请求的头 httpURLConnection.setRequestMethod("GET"); httpURLConnection.setReadTimeout(5000); // 设置下载文件的开始位置结束位置 httpURLConnection.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); // 获取的状态码 int code = httpURLConnection.getResponseCode(); // 判断是否成功 if (code == 206) { // 获取每个线程返回的流对象 InputStream is = httpURLConnection.getInputStream(); //获取文件的名称 String fileName = path.substring(path.lastIndexOf("/")+1); // 根据路径创建文件 File file = new File(sdFile, fileName); // 根据文件创建RandomAccessFile对象 RandomAccessFile raf = new RandomAccessFile(file, "rwd"); raf.seek(startIndex); // 定义读取的长度 int len = 0; // 定义缓冲区 byte b[] = new byte[1024 * 1024]; int total = 0; // 循环读取 while ((len = is.read(b)) != -1) { RandomAccessFile threadFile = new RandomAccessFile( new File(sdFile, threadId + ".txt"), "rwd"); threadFile.writeBytes((startIndex + total) + ""); threadFile.close(); raf.write(b, 0, len); // 已经下载的大小 total += len; //解决同步问题 synchronized (DownloadActivity.this) { currentProgress += len; progressBar.setProgress(currentProgress); //计算百分比的操作 l表示long型 final String percent = currentProgress*100l/progressBar.getMax()+"%"; DownloadActivity.this.runOnUiThread(new Runnable() { public void run() { tv_pb.setText("当前的进度是:"+percent); } }); //创建保存当前进度和百分比的操作 RandomAccessFile pbFile = new RandomAccessFile( new File(sdFile, "pb.txt"), "rwd"); pbFile.writeBytes(progressBar.getMax()+";"+currentProgress+";"+percent); pbFile.close(); } } raf.close(); is.close(); runOnUiThread(new Runnable() { public void run() { Toast.makeText(DownloadActivity.this, "当前线程--" + threadId + "--下载完毕", Toast.LENGTH_LONG).show(); } }); deleteRecordFiles(); } else { runOnUiThread(new Runnable() { public void run() { Toast.makeText(DownloadActivity.this, "服务器端下载错误", Toast.LENGTH_LONG).show(); } }); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } } // synchronized避免线程同步 public synchronized void deleteRecordFiles() { File sdFile = Environment.getExternalStorageDirectory(); threadRunning--; if (threadRunning == 0) { for (int i = 1; i <= 3; i++) { File recordFile = new File(sdFile, i + ".txt"); if (recordFile.exists()) { // 删除文件 recordFile.delete(); } File pbFile = new File(sdFile,"pb.txt"); if (pbFile.exists()) { pbFile.delete(); } } } }}
0 0
- 多线程下载断点下载
- 多线程下载,断点下载
- java 多线程断点下载
- 网络多线程断点下载
- 网络多线程断点下载
- 网络多线程断点下载
- android多线程断点下载
- 多线程断点下载原理
- 多线程断点下载文件
- java 多线程断点下载
- android 多线程断点下载
- android多线程断点下载
- 多线程断点下载器
- Java---多线程断点下载
- Java--多线程断点下载
- 断点多线程下载
- android多线程断点下载
- android,多线程断点下载
- 产品需求文档(PRD)写作(四) 写前准备(信息结构图)
- Java Integer.highestOneBit(int num) 源码解析
- Qt串口通讯实现--ARM开发板环境
- 安装配置elasticsearch
- 网络编程的头文件
- 多线程断点下载
- pat-bl-1031
- OpenCV3.0 Examples学习笔记(17)-morphology2.cpp-erode,dilate,morphologyEx函数实现数学形态学变换
- [Android] 图像各种处理系列文章合集
- svm 多分类机制
- Spring 面向切面(AOP)编程,注解
- nyoj1180Maze
- linux下批量替换文件中的字段
- Windoows10 x64下2个结构体变化