多线程下载文件

import java.io.File;
import java.net.URL;
import java.net.URLConnection;
import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
importandroid.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
importandroid.widget.TextView;

public class FileDownloadDemo extends Activity {

private EditTextdownloadUrl;
private EditTextdownloadFileName;
private EditTextdownloadThreadNum;
private ButtondownloadBt;
private ProgressBardownloadProgressBar;
private TextViewprogressMessage;
private int downloadedSize = 0;
private int fileSize = 0;

@Override
public void onCreate(BundlesavedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.main);

	downloadUrl =(EditText) findViewById(R.id.downloadUrl);
	downloadFileName = (EditText)findViewById(R.id.downloadFileName);
	downloadThreadNum = (EditText)findViewById(R.id.downloadThreadNum);
	progressMessage =(TextView)findViewById(R.id.progressMessage);
	downloadBt =(Button)findViewById(R.id.downloadBt);
	downloadProgressBar = (ProgressBar)findViewById(R.id.downloadProgressBar);
	downloadProgressBar.setVisibility(View.VISIBLE);
	downloadProgressBar.setMax(100);
	downloadProgressBar.setProgress(0);
	downloadBt.setOnClickListener(new OnClickListener(){
		
			public void onClick(View v){
			download();
		}
	});
}

private void download() {
	// 获取SD卡目录
	String dowloadDir = Environment.getExternalStorageDirectory()+ "/ideasdownload/";
	File file = new File(dowloadDir);
	//创建下载目录
	if (!file.exists()){
		file.mkdirs();
	}

	//读取下载线程数,如果为空,则单线程下载
	int downloadTN = Integer.valueOf("".equals(downloadThreadNum.getText()
	.toString()) ?"1" :downloadThreadNum.getText().toString());
	//如果下载文件名为空则获取Url尾为文件名
	int fileNameStart = downloadUrl.getText().toString().lastIndexOf("/");
	
	String fileName ="".equals(downloadFileName.getText().toString())? downloadUrl
	.getText().toString().substring(fileNameStart)
	: downloadFileName.getText().toString();
	//开始下载前把下载按钮设置为不可用
	downloadBt.setClickable(false);
	//进度条设为0
	downloadProgressBar.setProgress(0);
	//启动文件下载线程
	new downloadTask(downloadUrl.getText().toString(),Integer.valueOf(downloadTN), dowloadDir + fileName).start();
}

Handler handler = new Handler() {
	@Override
	public void handleMessage(Message msg) {
		//当收到更新视图消息时,计算已完成下载百分比,同时更新进度条信息
		int progress = (Double.valueOf((downloadedSize* 1.0 /fileSize * 100))).intValue();
		if (progress == 100) {
			downloadBt.setClickable(true);
			progressMessage.setText("下载完成!");
		} else{
			progressMessage.setText("当前进度:"+ progress + "%");
		}
			downloadProgressBar.setProgress(progress);
		}
	
};


public class downloadTask extends Thread {
	private int blockSize,downloadSizeMore;
	private int threadNum = 5;
	String urlStr, threadNo, fileName;
	
	public downloadTask(String urlStr, int threadNum, StringfileName) {
		this.urlStr = urlStr;
		this.threadNum = threadNum;
		this.fileName = fileName;
	}
	
	@Override
	public void run() {
		FileDownloadThread[] fds = new FileDownloadThread[threadNum];
		try {
			URL url = new URL(urlStr);
			URLConnection conn = url.openConnection();
			//获取下载文件的总大小
			fileSize =conn.getContentLength();
			//计算每个线程要下载的数据量
			blockSize = fileSize / threadNum;
			// 解决整除后百分比计算误差
			downloadSizeMore =(fileSize % threadNum);
			File file = new File(fileName);
			for (inti = 0; i< threadNum; i++) {
				//启动线程,分别下载自己需要下载的部分
				FileDownloadThread fdt =new FileDownloadThread(url, file,
				i * blockSize, (i + 1)* blockSize - 1);
				fdt.setName("Thread"+ i);
				fdt.start();
				fds =fdt;
				}
			boolean finished = false;
			while (!finished) {
				// 先把整除的余数搞定
				downloadedSize =downloadSizeMore;
				finished = true;
				for (inti = 0; i< fds.length; i++) {
					downloadedSize +=fds.getDownloadSize();
					if (!fds.isFinished()){
						finished = false;
					}
				}
				//通知handler去更新视图组件
				handler.sendEmptyMessage(0);
				//休息1秒后再读取下载进度
				sleep(1000);
			}
		} catch(Exception e) {
		
		}
		
}
}
}

//Java代码:
import java.io.BufferedInputStream;
importjava.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.URL;
import java.net.URLConnection;


importandroid.util.Log;


public class FileDownloadThread extends Thread{
private static final int BUFFER_SIZE=1024;
private URL url;
private File file;
private int startPosition;
private int endPosition;
private int curPosition;
//用于标识当前线程是否下载完成
private boolean finished=false;
private int downloadSize=0;
public FileDownloadThread(URL url,Filefile,int startPosition,int endPosition){
this.url=url;
this.file=file;
this.startPosition=startPosition;
this.curPosition=startPosition;
this.endPosition=endPosition;
}
@Override
public void run() {
	BufferedInputStream bis = null;
	RandomAccessFile fos =null; 
	byte[] buf = newbyte[BUFFER_SIZE];
	URLConnection con =null;
	try {
		con =url.openConnection();
		con.setAllowUserInteraction(true);
		//设置当前线程下载的起点,终点
		con.setRequestProperty("Range","bytes="+ startPosition + "-"+ endPosition);
		//使用java中的RandomAccessFile对文件进行随机读写操作
		fos = new RandomAccessFile(file, "rw");
		//设置开始写文件的位置
		fos.seek(startPosition);
		bis = new BufferedInputStream(con.getInputStream()); 
		//开始循环以流的形式读写文件
			while (curPosition < endPosition) {
				int len =bis.read(buf, 0,BUFFER_SIZE); 
				if (len ==-1) {
				break;
				}
				fos.write(buf, 0, len);
				curPosition =curPosition + len;
				if (curPosition > endPosition) {
					downloadSize+=len- (curPosition - endPosition) + 1;
				} else{
					downloadSize+=len;
				}
			}
			//下载完成设为true
			this.finished = true;
			bis.close();
			fos.close();
			} catch(IOException e) {
		Log.d(getName() +"Error:",e.getMessage());
	}
}


	public boolean isFinished(){
		return finished;
	}


	public int getDownloadSize(){
		return downloadSize;
	}
}



你可能感兴趣的:(多线程下载文件)