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)其中我们先实现布局 ...
随机推荐
- jqGrid TreeGrid 加载数据 排序 扩展
发现 jqGrid TreeGrid 加载的数据必须要排序 给了两种平滑数据模式尽然不内部递归 所以改了下源码加了个数据二次过滤器扩展 数据本该是这样的 结果没排序成这样了 (而且还得是从根节点到子节 ...
- SpringAOP的实现方式
1.使用SpringAPI实现AOP <aop:config> <!-- 切入点:需要操作的目标类中的目标方法 execution中只需要修改全类名 --> <aop:p ...
- AJAX—AJAX基础
AJAX简介 什么是AJAX AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步Javascript和XML”.即使用Javascript语言与服务器进行异 ...
- 09_Redis_消息订阅与发布
一:Redis 发布订阅 Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息. Redis 客户端可以订阅任意数量的频道. 下图展示了频道 c ...
- go包中的init() 函数
https://tutorialedge.net/golang/the-go-init-function/ ---------------------------------------------- ...
- 2.PAT 1001 害死人不偿命的(3 n + 1 )猜想
题目: 卡拉兹(Callatz)猜想: 对任何一个正整数 n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把 ( 砍掉一半.这样一直反复砍下去,最后一定在某一步得到 n=1.卡拉兹在 1950 ...
- HDU4465 Candy
Candy Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submi ...
- 微信小程序审核不通过的解决方法
前言 近来,微信小程序一直活跃在开发者的眼球中.很多开发者都投身微信小程序的开发中,而这些开发者,总是需要面对最后一道难题:如何以一种优雅的姿势来通过微信官方的审核.本文基于几天前提交审核的一次总结, ...
- 设置springboot、mysql、nginx,tomcat文件大小(大集合)
1.springboot设置文件大小 第一种: application.properties中添加 spring.http.multipart.maxFileSize=10MBspring.http. ...
- Python2.x与3.x版本区别Ⅲ
八进制字面量表示 八进制数必须写成0o777,原来的形式0777不能用了:二进制必须写成0b111. 新增了一个bin()函数用于将一个整https://www.xuanhe.net/数转换成二进制字 ...