您的位置:首页 > 理论基础 > 计算机网络

HttpURLConnection实现多线程下载资源contentLength()

2016-11-12 19:29 387 查看
package com.example.tyxiong.myapplication;

import android.app.Activity;
import android.app.ProgressDialog;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.EditText;

import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.ArrayList;

/*
*
* Android 网络应用.
*  3句概述:1 Android支持JDK的TCP/IP UDP的网络通信API.即可用ServiceSocket Socket来建立基于TCP/IP协议的网络通信;
*           也可以用DatagramSocket Dategrampacket MuliticastSocket来建立基于UDP协议的网络通信.
*         2 Android支持JDK的URL URLConnection等网络通信.
*         3 Android内置了HttpClient,方便的发送HTTP请求,简化了与网站间的交互.(可惜没有内置Web Service支持./有ksoap2-android项目)
*
*         IP协议:实现计算机发送接收分组数据.
*         TCP协议:提供可靠无差错的通信服务. 端对端的协议(为两个通信实体之间通信起到了重要作用), 重发机制(接收方收到数据,有应答,若无则发送方重发数据)
*         TCP IP功能互补,通常两者结合使用,统称TCP/IP协议.
*         TCP/IP协议通信建立过程: 服务器端(主动)接收客户端连接请求(accept()方法),当有客户端(Socket)发送连接请求时,
*         方法返回与之对应的Socket;通信链路建立.主客消失,可通过Socket通信.
*         使用步骤4步:
*          1 服务器端创建ServiceSocket对象,指定端口(大于1024) 默认IP
*          2 对象的实例方法accept(),接收客户端请求.阻塞线程,有请求时方法返回Socket对象
*          3 客户端创建Socket对象,连接到指定的服务器端口 new Socket(remoteAddress,port)
*          4 两个通信实体可通过Socket通信啦. 有方法getInputStream()/out.. 编码的问题linux平台用UTF-8字符集.
*
*          注意:android建立网络连接不允许在UI线程中进行.
*          设置读取数据超时(BufferReader readLine()阻塞):Socket有方法setSoTimeout(),超时可抛异常
*          设置连接服务器超时:步骤1 建无连接的Socket new Socket() 2 connect()方法设置
*
*          网络通信中多线程:服务器端:由于readLine()会阻塞线程,则每个Socket建立一个线程负责.
*                          客户端: 同样,需要一个线程读取服务器数据+ 然后主线程负责界面,用户输入.
*
*
*          URL,统一资源定位器,能打开URL指定网络数据的输入流(读取) 2个实例方法openStream()/打开连接的输入流 openURLConnection()/打开应用程序与URL资源间的连接对象
*          URL组成:协议名,主机名,端口,资源.
*          读取网络资源2步骤:
*              1 创建URL对象   2openStream()打开资源输入流,,读取吧.>>>
*
*     URLConnection提交请求:URL对象实例方法openURLConnection()方法->URLConnection对象-->发送请求,获取数据.
*     6方法 2+4 设置请求头字段  setRequestProperty(key,value)设置请求字段的值. addRequestProperty()为指定key追加value值.
*                 获取响应    getContent()/获取该URLConnection内容
*                            getHeaderField(string)获取指定响应头字段的值
*                            getInputStream()/URLConnection输入流,读取响应
*                            getOutputStram()/URLConnection输出流,发送请求参数
*            使用分4步骤:
*                   1 URL对象,方法 获取URLConnection对象
*                   2 设置URLConnection参数及请求字段属性
*                   3 若发送GET请求,直接connect()方法建立实际连接. Post请求则要打开URLConnection的输出流,先发送请求参数.
*                   4 远程资源可用,用获取响应方法读取资源.
*   注意:*****若既要发送请求,又要读取响应内容时,先发,再读.POST请求
*        ****若需发送POST请求,必须设置 setDoOutput(true) setDoInput(true)头字段.
*        ****用完关闭流.try/catch/final
*

*    HttpURLConnection URLConnection子类,增强,为Http访问提供了不4个便捷方法
*                         1 getResponseCode()//获取服务器响应代码
*                         2 getResponseMessage()//响应消息
*                         3 getRequestMethod()//获取发送请求的方法
*                         4 setRequestMethoe()//设置发送请求的方法.
*
*  多线程下载5步:
*         1 URL对象
*         2 获取URL对象指定资源数据大小(getContentLength())
*         3 本地建立与资源相同大小空文件
*         4 平分资源计算每条线程下载的字节部分.
*         5 创建,启动多条线程下载.
*
*
* HttpClient :1概述:Apache组织的项目,Android也内置了HttpClient支持.简单的Http客户端,用于发送HTTP请求
* 接收响应,增强版本的HttpURLConnection.使用5步:  3个对象 3个方法
*     1 创建HttpClient对象
*     2 若发送GET请求--HttpGet对象     POST请求--HttpPost对象
*     3 设置发送请求参数,,,可用setParams()/setEntity()
*     4 HttpClient对象execute()方法发送请求.该方法返回HttpResponse对象
*     5 HttpResponse对象 getEntity()方法,,获取响应内容.
*
*
*
*
*
*
*  HttpURLConnection URLConnection子类,增强,为Http访问提供了不4个便捷方法
*                         1 getResponseCode()//获取服务器响应代码
*                         2 getResponseMessage()//响应消息
*                         3 getRequestMethod()//获取发送请求的方法
*                         4 setRequestMethoe()//设置发送请求的方法.
* */

public class MainActivity extends Activity {

EditText show;
Handler handler;
private Thread thread;
EditText fileName;
EditText threadCount;
ProgressDialog progressDialog;
private int progress;
private int MAX = 100;
DownUtils downUtils;
String url;
String path;
int count;
public void send(View view) {//向服务器发送数据....
url = show.getText().toString();
path = fileName.getText().toString();
count = Integer.parseInt(threadCount.getText().toString().trim());

progressDialog.show();
thread.start();
}//发送GET请求...

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
show = (EditText) findViewById(R.id.show);

fileName = (EditText) findViewById(R.id.fileName);
threadCount = (EditText) findViewById(R.id.count);

progressDialog = new ProgressDialog(this);
progressDialog.setTitle("下载");
progressDialog.setIndeterminate(false);
progressDialog.setCancelable(false);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setMessage("正在下载...");
progressDialog.setMax(MAX);

handler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == 0x11) {
progressDialog.setProgress(progress);
}
}
};

thread = new Thread() {
@Override
public void run() {
downUtils = new DownUtils(url, path, count);
downUtils.sendGet();
while (progress < MAX) {
float position = downUtils.getProgress();
progress = (int) (MAX * position);
try {
sleep(1 * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

handler.sendEmptyMessage(0x11);
}
progressDialog.dismiss();
}
};

}
}

class DownUtils {
String link;
/*  "http://p.gdown.baidu.com/ab67d1f87dda5edd22d919fc5a33bad644220b671bb3bb17fd6f8849a61ed2c3c7e9c44f13348ef75f6bcbdb8cdc5c867bcf7dd31f353abeb47a285ab0b588c5c0df7dcdbcf395acd80b500258e99d064d92bac54af82bd95b7553bd86e2bc83ce217398cfb18bd8fd5e6a6f506db32f75cb5e965207230404b400a9fdd2fdc8e20c4215f9fde290e5b22eed14479ddd43a35e954f30c2e8ed119b7239a659fbf59390a45f51edaab818ef4eeb14a4011dd043f84f4b70f4d49f8a5b0571d5b1d8bdb84b2d49d3687d5b43e0fe513b59f3beef45c6121fd0088e20ad370cb22e02207716b95d8f627a5fe9d79f99b06852651f73c5d0e63476b8148506a88909fb0947b3e5510573632887aeee2e6b871dfe70d2ee93fc2fad2997f2a2845e1f40ac0b9ddbcf4e679cd8b0600f1a93af5774d530038d59a073d1e7f97ef1b488";*/
String path;
int COUNT;

public DownUtils(String link, String path, int COUNT) {
this.link = link;
this.path = "/mnt/sdcard/"+path;
this.COUNT = COUNT;
}

ArrayList<DownThread> list = new ArrayList<>();
int fileSize = 0;
int subSize = 0;

public float getProgress() {

int num = 0;

for (int i = 0; i < list.size(); i++) {
num += list.get(i).progress;
}
return 1.0f * num / fileSize;

}

public void sendGet() {

RandomAccessFile file = null;
try {
final HttpURLConnection urlConnection;
URL url = new URL(link);
urlConnection = (HttpURLConnection) url.openConnection();//1获取与远程资源的连接.
urlConnection.setConnectTimeout(10 * 1000);

urlConnection.setRequestProperty("accept", "*/*");
urlConnection.setRequestProperty("connection", "Keep-Alive");
urlConnection.setRequestProperty("charset", "utf-8");//设置请求字段属性.
urlConnection.getRequestMethod();

b41a
urlConnection.setRequestMethod("GET");                   //便捷方法设置发送请求方法
fileSize = urlConnection.getContentLength();
urlConnection.disconnect();
file = new RandomAccessFile(path, "rw");
file.setLength(fileSize);
Log.w("xxx", "sendGet: 需要下载文件大小" + fileSize);
subSize = fileSize / COUNT;
for (int i = 0; i < COUNT; i++) {

DownThread newThread = new DownThread(i * subSize, subSize);//// TODO: 11/11/2016
list.add(newThread);
newThread.start();
}

} catch (IOException e) {
e.printStackTrace();
} finally {
try {
assert file != null;
file.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}

class DownThread extends Thread {
public int position = 0;
int length = 0;
int progress = 0;

public DownThread(int position, int length) {
this.position = position;
this.length = length;

}

@Override
public void run() {

HttpURLConnection urlConnection;
URL url;
try {
RandomAccessFile randomAccessFile = new RandomAccessFile(path, "rw");
url = new URL(link);
urlConnection = (HttpURLConnection) url.openConnection();//1获取与远程资源的连接.
urlConnection.setConnectTimeout(10 * 1000);

urlConnection.setRequestProperty("accept", "*/*");
urlConnection.setRequestProperty("connection", "Keep-Alive");
urlConnection.setRequestProperty("charset", "utf-8");//设置请求字段属性.
urlConnection.getRequestMethod();
urlConnection.setRequestMethod("GET");                   //便捷方法设置发送请求方法
urlConnection.connect();
InputStream inputStream = urlConnection.getInputStream();
long j = 0;
while (j < position) {
j += inputStream.skip(position - j);
}
randomAccessFile.seek(position);

int read = 0;
byte[] buffer = new byte[1024];
while (progress < length && read != -1) {
read = inputStream.read(buffer, 0, buffer.length);
randomAccessFile.write(buffer, 0, read);
progress += read;
}

randomAccessFile.close();
inputStream.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}

}
}

}
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
![运行效果](http://img.blog.csdn.net/20161112192835504)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息