import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Activity;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Toast; public class MainActivity extends Activity { private EditText etPath;
private EditText etThread;
private LinearLayout llContent;
int threadCount = 3;
private String path; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etPath = (EditText) findViewById(R.id.et_path);
etThread = (EditText) findViewById(R.id.et_thread);
llContent = (LinearLayout) findViewById(R.id.ll_content);
} public void download(View v) {
path = etPath.getText().toString().trim();
String count = etThread.getText().toString().trim();
if (TextUtils.isEmpty(path) || !path.startsWith("http")) {
Toast.makeText(this, "请输入正确的网址,否则,兄弟我没法干活。。。", 0).show();
return;
} if (!TextUtils.isEmpty(count)) {
threadCount = Integer.valueOf(count);
} // 移除所有的view
llContent.removeAllViews();
// 有多少个线程,就加载多少个进度条
for (int i = 0; i < threadCount; i++) {
ProgressBar pb = (ProgressBar) View.inflate(this,
R.layout.progressbar, null);
llContent.addView(pb);
}
// 开启线程
new Thread() {
public void run() {
requestNet4DownLoad();
}
}.start();
} /**
* 下载
*/
private void requestNet4DownLoad() {
try {
// 1. 在客户端创建和服务器资源一样大小的空文件
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setConnectTimeout(3000);
conn.setRequestMethod("GET");
int code = conn.getResponseCode();
// 服务器资源文件的大小
int fileLength = 0;
if (code == 200) {
fileLength = conn.getContentLength();
System.out.println("文件大小:" + fileLength);
// //可选,可以不写,检测硬盘的空间够不够用
// RandomAccessFile raf = new RandomAccessFile(getFilePath(),
// "rw");
// //在硬盘上创建控件
// raf.setLength(fileLength);
// raf.close();
}
// 每个线程下载的区块大小
int blockSize = fileLength / threadCount;
// 2. 客户端开启多个线程去下载服务器的资源
for (int threadId = 0; threadId < threadCount; threadId++) {
int startIndex = threadId * blockSize;
int endIndex = (threadId + 1) * blockSize - 1;
// 最后一个线程,修正下载的结束位置
if (threadId == threadCount - 1) {
endIndex = fileLength - 1;
}
// 开启线程
new DownLoadThread(startIndex, endIndex, threadId).start();
}
} catch (Exception e) {
e.printStackTrace();
}
} class DownLoadThread extends Thread {
//开始位置
int startIndex;
//结束位置
int endIndex;
//线程ID
int threadId;
//断点的位置
int lastDownPos;
private ProgressBar mPb;
//最大的进度
int maxProgress;
//当前下载的进度
int progress;
//理论上开始下载的位置
int fistIndex; public DownLoadThread(int startIndex, int endIndex, int threadId) {
super();
progress = startIndex;//初始化
fistIndex = startIndex;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.threadId = threadId;
lastDownPos = startIndex;//初始
mPb = (ProgressBar) llContent.getChildAt(threadId);
//设置最大的进度
maxProgress = endIndex - startIndex;
mPb.setMax(maxProgress);
}
@Override
public void run() {
super.run();
System.out.println("理论上线程 : "+ threadId + " : "+ startIndex+" ~ "+endIndex)
try {
File tmpFile = new File(getFileTmpPath(threadId));
if (tmpFile != null && tmpFile.exists() && tmpFile.length() > 0) {
FileInputStream fis = new FileInputStream(tmpFile);
BufferedReader br = new BufferedReader(new InputStreamReader(fis));
int text = Integer.valueOf(br.readLine());
lastDownPos = text;//多次断点
startIndex = lastDownPos; //接受上一次断点的位置请求网络
br.close();
System.out.println("断点后线程 : "+ threadId + " : "+ startIndex+" ~ "+endIndex);
}
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(3000);
//重要,设置请求的范围 conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex); //部分请求成功 206 int code = conn.getResponseCode();
System.out.println(" code = "+code);
if (code == 206) {
RandomAccessFile raf = new RandomAccessFile(getFilePath(), "rw");
//重要,写文件之前定位
raf.seek(startIndex);
//获取这个线程对应的一块资源
InputStream is = conn.getInputStream();
byte[] buffer = new byte[512];
int len = -1;
while((len = is.read(buffer)) != -1){
//计算存储的位置
lastDownPos += len;
RandomAccessFile r = new RandomAccessFile(getFileTmpPath(threadId), "rwd"); String pos = String.valueOf(lastDownPos);
//存储断点的位置
r.write(pos.getBytes());
r.close();
raf.write(buffer, 0, len);
//设置进度条的进度
progress = lastDownPos - fistIndex;
mPb.setProgress(progress);
}
raf.close();
}
// 3. 每个线程都下载完毕,整个资源就下载完了
System.out.println("线程 "+threadId+" 干完活了!");
//删除临时的进度文件
System.out.println(tmpFile.delete());
} catch (Exception e) {
e.printStackTrace();
}
}
} /**
* 获取文件的存储路径
*/
String getFilePath(){
int index = path.lastIndexOf("/")+1;
return "/mnt/sdcard/"+path.substring(index);
} **
* 存储进度的临时文件
*/ String getFileTmpPath(int threadId){
return getFilePath()+threadId+".txt";
}
}
 
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
/**
* 操作字符串
*/ public class StringUtils {
/**
* 从流中转成字符串
*
* @param is
* 输入流
* @return null表示失败
*/ public static String parseStream2Str(InputStream is) {
//内存输出流
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = -1;
byte[] buffer = new byte[1024*8];
try {
while((len = is.read(buffer)) != -1){
baos.write(buffer, 0, len);
}
return new String(baos.toByteArray());
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}

HttpURLConnection断点下载的更多相关文章

  1. android网络编程之HttpUrlConnection的讲解--实现文件断点下载

    1.没有实现服务器端,下载地址为网上的一个下载链接. 2.网络开发不要忘记在配置文件中添加访问网络的权限 <uses-permission android:name="android. ...

  2. Java实现多线程断点下载(下载过程中可以暂停)

    线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启好几个下载通道.当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配. ...

  3. 安卓(android)之实现断点下载功能

    一.建立实体类 1.文件实体类 package com.example.zjw.myapplication.dao; import java.io.Serializable; /** * 预下载文件实 ...

  4. 【Java EE 学习 22 下】【单线程下载】【单线程断点下载】【多线程下载】

    一.文件下载简述 1.使用浏览器从网页上下载文件,Servlet需要增加一些响应头信息 (1)response.setContentType("application/force-downl ...

  5. Android 学习之--android多线程断点下载

    我们平时都用"迅雷"下载软件,当下载到一半的时候突然断网,下次开启的时候能够从上次下载的地方继续下载,而且下载速度很快,那么这是怎么做到的呢! 其实它的“快”其实就是多线程的下载实 ...

  6. Android 学习笔记之使用多线程实现断点下载...

    PS:莫名其妙的迷茫... 学习内容: 1.使用多线程实现文件下载...   多线程下载是加快下载速度的一种方式..通过开启多个线程去执行一个任务..可以使任务的执行速度变快..多线程的任务下载时常都 ...

  7. 33、多线程断点下载的实现&界面的更新

    <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...

  8. Java之多线程断点下载的实现

    RandomAccessFile类: 此类的实例支持对随机訪问文件的读取和写入.随机訪问文件的行为相似存储在文件系统中的一个大型 byte 数组. 存在指向该隐含数组.光标或索引,称为文件指针.输入操 ...

  9. Android(java)学习笔记216:多线程断点下载的原理(Android实现)

    之前在Android(java)学习笔记215中,我们从JavaSE的角度去实现了多线程断点下载,下面从Android角度实现这个断点下载: 1.新建一个Android工程: (1)其中我们先实现布局 ...

随机推荐

  1. mock.js学习之路一(Vue中使用)

    1.安装mockjs 2.配置mockjs在开发环境中启用,生产环境中禁用 3.创建mock文件夹,以及mock数据文件 4.在main.js中引入与否 5.页面获取数据 testMock(){ th ...

  2. error connection reset by peer 104

    connection reset by peer的常见原因 1.服务器的并发连接数超过了其承载量,服务器会将其中一些连接关闭:2. errno = 104错误表明你在对一个对端socket已经关闭的的 ...

  3. go语言中regexp包中的函数和方法

    // regexp.go ------------------------------------------------------------ // 判断在 b 中能否找到正则表达式 patter ...

  4. 了解认识asp.net运行机制

    asp.net  运行机制 下面了解认识httpModule 要创建一个httpModule类 using System;using System.Collections.Generic;using ...

  5. Java中的集合(上):概述、Collection集合、List集合及其子类

    一.集合的体系结构 二.Collection集合 1.基本使用 如下代码 import java.util.ArrayList; import java.util.Collection; public ...

  6. JSON添加注释的问题

    JSON有两种数据结构: 名称/值对的集合:key : value样式: 值的有序列表:就是Array: 而在JSON的文档中说明只要是不符合上面两种结构的都不被支持,并提示错误 添加注释//或者/* ...

  7. 洛谷P2341 [HAOI2006]受欢迎的牛 (Tarjan,SCC缩点)

    P2341 [HAOI2006]受欢迎的牛|[模板]强连通分量 https://www.luogu.org/problem/P2341 题目描述 每头奶牛都梦想成为牛棚里的明星.被所有奶牛喜欢的奶牛就 ...

  8. Codeforces Round #589 (Div. 2) B. Filling the Grid

    链接: https://codeforces.com/contest/1228/problem/B 题意: Suppose there is a h×w grid consisting of empt ...

  9. RecursiveTask和RecursiveAction的使用 以及java 8 并行流和顺序流(转)

    什么是Fork/Join框架        Fork/Join框架是Java7提供了的一个用于并行执行任务的框架, 是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架. 我 ...

  10. vue cli 3.x 配置使用 sourceMap

    项目使用vue cli 3.x搭建,没有了配置文件,如何更方便的查找到对应的scss文件,配置项目支持sourceMap方式? 分二步走: 1.项目根目录(不是src目录,不要搞错了)添加vue.co ...