Android http 多线程下载

今天学习了一些http多线程下载,简单整理一下,便于今后查阅。

URLConnection 可以很方便的与指定的站点交换信息,URLConnect有个子类:HttpURLConnection,HttpURLConnection增加了一些操作http资源的便捷方法。


实现多线程下载步骤如下:

1)创建URL对象。

2)获取指定URL对象所指定资源的大小,使用getContentlength方法。

3)计算每个线程要下载资源的哪个部分(从某个字节开始到哪个字节介绍)。

4)依次创建线程,启动多线程来下载网络指定的部分。


创建downloadUitl类,来创建HttpURLConnetion对象,获取下载资源的大小,创建多线程,来下载指定部分的内容,代码如下:

package com.example.mutidownload;

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

import android.app.DownloadManager;

public class DownloadUntil {

	//set path of resource
	String path;				 //记录资源路径
	private int threadNum;		 //保存下载文件的大小
	private long fileSize;		 //保存下载文件的大小
	private String targeFile;	 //下载文件的本地位置
	DownloadThread[] threads;    //线程池
	public DownloadUntil(String targeFile, int threadNum,String path) {
		// TODO Auto-generated constructor stub
		this.path = path;
		this.threadNum = threadNum;
		this.targeFile = targeFile;
		threads = new DownloadThread[threadNum];
	}
	
	//多线程下载的核心代码
	public void download() throws IOException{
		URL url = new URL(path);
		
		//build http header
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();
		conn.setConnectTimeout(10000);
		conn.setRequestMethod("GET");
		conn.setRequestProperty("Accept", "image/gif,image/jpeg,*/*");
		conn.setRequestProperty("Accept-Language", "zh-CN");
		conn.setRequestProperty("Charset", "UTF-8");
		conn.setRequestProperty("User-Agent", "Mozilla/4.0(compatible;MSIE6.0;Windows NT 5.0)");
		conn.setRequestProperty("Connect", "Keep-Alive");
		
		
		fileSize = conn.getContentLength();  //获取下载下载文件大小
		conn.disconnect();
		long currentPartSize = fileSize/threadNum;  //计算每个线程要下载的文件大小
		RandomAccessFile file = new RandomAccessFile(targeFile, "rw");//打开本地文件,来保存下载数据
		file.setLength(fileSize);
		file.close();
		
		//创建多线程
		for(int i = 0; i< threadNum; i++){
			long startPos = i*currentPartSize; //计算每个线程所要下载资源的起始位置
			RandomAccessFile currentPart = new RandomAccessFile(targeFile, "rw");
			currentPart.seek(startPos);//set download focus in local file
			threads[i] = new DownloadThread(startPos,currentPartSize,currentPart);//create thread
			threads[i].start();
		}
	}
	//download rate
	public float getDownloadProgress(){
		int sumSize = 0;
		for (int i = 0; i < threads.length; i++) {
			sumSize += threads[i].length;
		}
		return (float) (sumSize * 1.0/fileSize * 1.0);
	}
	//create download thread
	private class DownloadThread extends Thread{
		public int length = 0;  //记录此线程已下载资源的长度
		private long startPos;  //在下载流中,此线程要下载的初始位置
		private long currentPartSize; //此线程下载内容的总长度
		private RandomAccessFile currentPart;//本地文件句柄
		public DownloadThread(long startPos, long currentPartSize,
				RandomAccessFile currentPart) {
			// TODO Auto-generated constructor stub
			this.startPos = startPos;
			this.currentPart = currentPart;
			this.currentPartSize = currentPartSize;
		}

		// 单个下载和数据读写的核心代码
		public void run(){
			try {
				//creat url connect
				URL url = new URL(path);
				HttpURLConnection httpConn = (HttpURLConnection)url.openConnection();
				
				//set header
				httpConn.setConnectTimeout(10000);
				httpConn.setRequestMethod("GET");
				httpConn.setRequestProperty("Accept", "image/gif,image/jpeg,*/*");
				httpConn.setRequestProperty("Accept-Language", "zh-CN");
				httpConn.setRequestProperty("Charset", "UTF-8");
				httpConn.setRequestProperty("User-Agent", "Mozilla/4.0(compatible;MSIE6.0;Windows NT 5.0)");
				httpConn.setRequestProperty("Connect", "Keep-Alive");
				
				
				InputStream is = httpConn.getInputStream();//get inputstream
				is.skip(startPos);   //把流中的索引指定到此线程所要下载的位置
				
				byte[] buffer = new byte[1024];
				int hasRead = 0;
				while (length < currentPartSize &&
						(hasRead = is.read(buffer)) != -1) {
					currentPart.write(buffer, 0, hasRead);    //把流中数据写入到本地文件中(在前面已经指定了文件索引,所以在此直接保存就可以
					length+=hasRead;
				}
				currentPart.close();
				is.close();
			} catch (MalformedURLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}
}

 

Activity 部分代码:

package com.example.mutidownload;

import java.io.IOException;
import java.util.Timer;
import java.util.TimerTask;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;

public class MainActivity extends Activity {

	int mProgress = 0;
	ProgressBar progress;
	
    Handler handler = new Handler(){
    	@Override
    	public void handleMessage(Message msg) {
    		// TODO Auto-generated method stub
    		super.handleMessage(msg);
    		if (msg.what == 0x01) {
    			progress.setProgress(mProgress);
			}
    	}
    };
    
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		final EditText url = (EditText)findViewById(R.id.url);
		progress = (ProgressBar)findViewById(R.id.progress);
		Button download = (Button)findViewById(R.id.download);
		
		download.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				final DownloadUntil donwloadUntil = new DownloadUntil(url.getText().toString(), 5, "mnt/sd/download");
				
				try {
					donwloadUntil.download();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				final Timer timer = new Timer();
				timer.schedule(new TimerTask() {
					
					@Override
					public void run() {
						// TODO Auto-generated method stub
						mProgress = (int)donwloadUntil.getDownloadProgress()* 100;
						handler.sendEmptyMessage(0x01);
						if (mProgress > 100) {
							timer.cancel();
						}
					}
				}, 0, 100);
			}
		});
		
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

}

 

你可能感兴趣的:(多线程,android,http,下载)