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. JavaSpring【七、AspectJ】

    AspectJ 概念 @AspectJ类似纯Java注解的普通Java类 Spring可以使用AspectJ来作为切入点 AOP在运行时仍是纯SpringAOP,对AspectJ无依赖 配置: 对@A ...

  2. redis系列一: windows下安装redis

    一. 下载Redis Redis 支持 32 位和 64 位.这个需要根据你系统平台的实际情况选择,这里我们下载 Redis-x64-xxx.zip压缩包到 C 盘,解压后,将文件夹重新命名为 red ...

  3. Vmvare 虚拟机固定IP

    首先我们打开虚拟机的虚拟网络编辑器,打开vmvare菜单栏的编辑,选择虚拟网络编辑器.   在打开的网络虚拟器中,会看到相关信息,虚拟机网络类型采用的NAT模式,子网地址是192.168.89.0,虚 ...

  4. Ubuntu系统---安装 WPS

     Ubuntu系统---安装 WPS Ubuntu桌面系统自带了Libreoffice办公软件,但是个人觉得它不符合我们中国人的使用习惯.搜索了Office For Linux,好麻烦,也会出现问题, ...

  5. Python:出现UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc9 in position 0: invalid continuation byte问题

    我在导入一个csv文件的时候出现了一个问题 报错的内容是这样的: UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc9 in positio ...

  6. js技术javascript 该重视

    当下,js大有挤压php java asp.net之类后端语言的趋势,直接js html5 socket与后端python c c++ 等通信 更不用提二维 三维计算展示 方面 医院呼叫 报警  处理 ...

  7. java动态代理框架

             java动态代理是一个挺有意思的东西,他有时候可以被使用的很灵活.像rpc的调用,调用方只是定义的一个接口,动态代理让他匹配上对应的不同接口:mybatis内部的实现,编码时,只是实 ...

  8. visual studio 和visual studio code 的区别是什么?

    区别有三: 区别一:含义不一样. Visual Studio(简称VS)是美国微软公司的开发工具包系列产品,是一个基本完整的开发工具集,它包括了整个软件生命周期中所需要的大部分工具,如UML工具.代码 ...

  9. hdu3715 Go Deeper[二分+2-SAT]/poj2723 Get Luffy Out[二分+2-SAT]

    这题转化一下题意就是给一堆形如$a_i + a_j \ne c\quad (a_i\in [0,1],c\in [0,2])$的限制,问从开头开始最多到哪条限制全是有解的. 那么,首先有可二分性,所以 ...

  10. MyBatis执行原理图

    作者:W&L 推荐: 陶邦仁的博客 (1)加载配置并初始化       触发条件:加载配置文件 配置来源于两个地方,一处是配置文件,一处是Java代码的注解,将SQL的配置信息加载成为一个个M ...