HttpURLConnection断点下载
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断点下载的更多相关文章
- android网络编程之HttpUrlConnection的讲解--实现文件断点下载
1.没有实现服务器端,下载地址为网上的一个下载链接. 2.网络开发不要忘记在配置文件中添加访问网络的权限 <uses-permission android:name="android. ...
- Java实现多线程断点下载(下载过程中可以暂停)
线程可以理解为下载的通道,一个线程就是一个文件的下载通道,多线程也就是同时开启好几个下载通道.当服务器提供下载服务时,使用下载者是共享带宽的,在优先级相同的情况下,总服务器会对总下载线程进行平均分配. ...
- 安卓(android)之实现断点下载功能
一.建立实体类 1.文件实体类 package com.example.zjw.myapplication.dao; import java.io.Serializable; /** * 预下载文件实 ...
- 【Java EE 学习 22 下】【单线程下载】【单线程断点下载】【多线程下载】
一.文件下载简述 1.使用浏览器从网页上下载文件,Servlet需要增加一些响应头信息 (1)response.setContentType("application/force-downl ...
- Android 学习之--android多线程断点下载
我们平时都用"迅雷"下载软件,当下载到一半的时候突然断网,下次开启的时候能够从上次下载的地方继续下载,而且下载速度很快,那么这是怎么做到的呢! 其实它的“快”其实就是多线程的下载实 ...
- Android 学习笔记之使用多线程实现断点下载...
PS:莫名其妙的迷茫... 学习内容: 1.使用多线程实现文件下载... 多线程下载是加快下载速度的一种方式..通过开启多个线程去执行一个任务..可以使任务的执行速度变快..多线程的任务下载时常都 ...
- 33、多线程断点下载的实现&界面的更新
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- Java之多线程断点下载的实现
RandomAccessFile类: 此类的实例支持对随机訪问文件的读取和写入.随机訪问文件的行为相似存储在文件系统中的一个大型 byte 数组. 存在指向该隐含数组.光标或索引,称为文件指针.输入操 ...
- Android(java)学习笔记216:多线程断点下载的原理(Android实现)
之前在Android(java)学习笔记215中,我们从JavaSE的角度去实现了多线程断点下载,下面从Android角度实现这个断点下载: 1.新建一个Android工程: (1)其中我们先实现布局 ...
随机推荐
- 【loj#2133 && luoguP2178】[NOI2015]品酒大会
题目传送门:loj#2133 luoguP2178 简要题意:给定一个字符串\(s\),每个后缀都有权值,对于每个长度\(len\),求出所有最长公共前缀\(\geq len\)的后缀对的总数 ...
- Java通过JDBC连接SQL Server2017数据库
一.需要明白的基础知识 数据库名 驱动jar(x表示版本号) 具体驱动类 连接字符串(ip地址,端口号,名字) Oracle ojdbc-x.jar oracle.jdbc.oracleDriver ...
- IDEA 运行报错:WARN: Establishing SSL connection
使用JDBC连接数据库时出现报错, 报错内容:Wed Sep 26 14:30:31 CST 2018 WARN: Establishing SSL connection without server ...
- HDU 2897 bash 博弈变形
一堆石子N个 每个人最少取P个 最多取Q个 最后取光的人输 问谁赢 X=N%(P+Q) X=0则先手取Q个必胜 X<=P则后手胜 X>P则先手取P个必胜 #include <ios ...
- celery+django+mq 异步任务与定时任务
参考 celerypip install celery==4.1.1https://www.cnblogs.com/wdliu/p/9530219.htmlhttps://www.jianshu.co ...
- windows OpenCV 2.4.9 Python 2.7配置
1 .下载 OpenCV 2.4.9 .下载OpenCV-2.4.9,使用方便 下载地址 2. OpenCV-自解压文件,直接运行.即可解压.解压到想要的opencv文件夹里E:\Programme\ ...
- 基于STM32调试工具STM-STUDIO-STM32的使用
手上有stlink下载器,正好看到官网有这个工具,可以在运行中实时查看变量的数据.这一点和ucos的ucprobe很类似. 参考https://mp.weixin.qq.com/s?src=11&am ...
- 《Redis 设计与实现》读书笔记(四)
独立功能的实现 十八.发布和订阅 发布和订阅由下面几条命令组成 PUBLISH,发布消息,例如PUBLISH SUBSCRIBE,订阅某个频道 SUBSCRIBE UNSUBSCRIBE 退订某个频道 ...
- @Transactional(转)
概述@Transactional 是声明式事务管理 编程中使用的注解 添加位置 接口实现类或接口实现方法上,而不是接口类中访问权限:public 的方法才起作用 @Transactional 注解应该 ...
- 'telnet' is not recognized as an internal or external command
http://blog.csdn.net/lubinsu/article/details/7294870 使用telnet的时候出现如下提示:'telnet' is not recognized ...