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)其中我们先实现布局 ...
随机推荐
- 微信小程序html(wxml)传参
欢迎加入前端交流群交流知识:749539640 习惯了vue.angular用微信小程序有时候真感觉非人类..需要用data-xxx 先说下我们在vue.angular里事件传参 //html < ...
- 对于在tinyOS中读取MPU6050数据卡死的总结
最近这几天一直给tinyOS挂载外设,从最简单的LED.KEY,再到串口,这些都没什么大问题,无非就是先初始化tinyOS,再初始化硬件外设,接着启动tinyOS,然后tinyOS去寻找优先级最高的任 ...
- 12_Redis_服务器命令
一:Redis 服务器:Redis 服务器命令主要是用于管理 redis 服务
- idou老师教你学Istio 04:Istio性能及扩展性介绍
Istio的性能问题一直是国内外相关厂商关注的重点,Istio对于数据面应用请求时延的影响更是备受关注,而以现在Istio官方与相关厂商的性能测试结果来看,四位数的qps显然远远不能满足应用于生产的要 ...
- python -m pip install [package] --no-deps
python -m pip install [package] --no-deps 有些 packages 会依赖一些其它的 package,当我们离线安装 whl 的时候,就无法联网下载依赖包,所 ...
- OI界的事
随时更新: 目前在中大型考试上已经因为freopen相关的锅导致此题爆零共有: 5次.并且因此参加不了提高组(菜到无人反驳) 本人:学oi半年的练习生)蒟蒻 ,擅长水红题,橙题,博客,以及电子方面. ...
- [转载]springboot--常用注解--@configration、@Bean
springboot--常用注解--@configration.@Bean @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME ...
- Linux权限操作(用户和组)
useradd 添加用户useradd -u uid user 创建指定uid的用户-o 配合-u 不检查uid的唯一性-d 指定家目录-s 指定shell-r 创建系统用户-m 强制创建家目录-M ...
- Unity 截图选择框,中间全透明,边缘半透明
效果:点击白色框可拖拽选择区域 代码: using System.Collections; using System.Collections.Generic; using UnityEngine; u ...
- [RxJS] RxJS Advanced Patterns Operate Heavily Dynamic UIs
Check the playground. import {Counter, CountDownState, ConterStateKeys, PartialCountDownState} from ...