您的位置:首页 > 编程语言 > Java开发

Java多线程下载

2012-09-10 10:22 369 查看
package org.yang.utils;

/**
* @author 杨志永
* email ljy520zhiyong@163.com
* QQ 929168233
* Date 2012-9-10
*/

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

public class MultiDownload implements Runnable {
/** threadId 表示当前线程的Id .只能外界只能获取不能设置 */
private int threadId;

/** threadNumbers 表示用多少条线程来下载. 外界可以设置下载的线程数,默认为5条线程。可以get和set */
private int threadNumbers = 5;

/** 每条线程要下载的块大小,单位为byte。只能外界只能获取不能设置 */
private int blockSize;

/** url 表示网络文件的URL地址的字符串表示形式 . 只能从外界设置(set),设置完后可以get */
private String url;

/** savePathDir 表示要保存的本地路径目录 ,必须要设置。注意是目录 */
private String savePathDir;

/** saveFile 表示要保存的本地文件 */
private File saveFile;

/** fileName 表示文件名 */
private String fileName;

public void setFileName(String fileName) {
this.fileName = fileName;
}

public int getThreadId() {
return threadId;
}

public int getThreadNumbers() {
return threadNumbers;
}

public void setThreadNumbers(int threadNumbers) {
this.threadNumbers = threadNumbers;
}

public int getBlockSize() {
return blockSize;
}

public String getUrl() {
return url;
}

public void setUrl(String url) {
this.url = url;
}

public String getSavePathDir() {
return savePathDir;
}

public void setSavePathDir(String savePathDir) {
this.savePathDir = savePathDir;
}

public File getSaveFile() {
return saveFile;
}

public void setSaveFile(File saveFile) {
this.saveFile = saveFile;
}

public MultiDownload() {
}

/**
*
* @param threadId
*            当前线程的Id
* @param blockSize
*            每条线程要下载的大小,单位为byte
* @param url
*            网络资源的url字符串
* @param saveFile
*            要保存的路径
*/
public MultiDownload(int threadId, int blockSize, String url, File saveFile) {
super();
this.blockSize = blockSize;
this.threadId = threadId;
this.url = url;
this.saveFile = saveFile;
}

public void startDownloadFile() throws IOException {
/** 创建一个URL对象,参数为网络资源的字符串,用来与网络资源文件建立连接 */
URL url = new URL(this.url);

/** 创建一个网络连接对象,并打开该连接 */
HttpURLConnection httpURLConnection = (HttpURLConnection) url
.openConnection();

/** 设置超时 */
httpURLConnection.setConnectTimeout(5000);

/** 设置请求方式,这里设置为GET */
httpURLConnection.setRequestMethod("GET");

try {

/** 判断连接的返回状态码,200表示为正常状态 */
if (httpURLConnection.getResponseCode() == 200) {
/** 获取网络文件的总大小,单位为byte */
int fileLength = httpURLConnection.getContentLength();

System.out.println("要下载的文件总大小为: " + fileLength + " bytes");
System.out.println("要下载的文件名为: " + this.getFileName());

/** 要保存为本地的路径表示的文件对象,为 保存的目录 + 网络文件的文件名 */
File saveFiles = new File(savePathDir + File.separator
+ this.getFileName());

/** 建立一个随机访问的文件对象,并设置它的大小为网络文件资源的文件总大小,即 fileLength */
RandomAccessFile randomAccessFile = new RandomAccessFile(
saveFiles, "rwd");
randomAccessFile.setLength(fileLength);
randomAccessFile.close();

/** 计算每条线程要下载的块大小blockSize,单位为byte */
int blockSize = fileLength % this.threadNumbers == 0 ? fileLength
/ this.threadNumbers
: fileLength / this.threadNumbers + 1;
System.out.println("每条线程要下载的文件大小为: " + blockSize + " bytes");

/** 启动所有线程来进行下载 */
for (int threadId = 0; threadId < this.threadNumbers; threadId++) {

new Thread(new MultiDownload(threadId, blockSize, this.url,
saveFiles)).start();
}

}
} catch (Exception e) {
System.out.println("连接出错啦:第[" + this.threadId + "]条线程:");
e.printStackTrace();
}
}

@Override
public void run() {
System.out.println("第" + this.threadId + "条线程启动!");
/** start为每条线程从该位置开始下载 ,公式为 【开始位置=线程的ID*每条线程要下载的块大小】 */
int start = this.threadId * this.blockSize;

/**
* end 为每条线程从该位置结束下载 ,公式为 【结束位置=(线程的ID+1)*每条线程要下载的块大小 -1
* ,减1是因为文件的长度表示范围为:0~fileLength】
*/
int end = (this.threadId + 1) * this.blockSize - 1;

try {
/** 打开要保存的本地文件的随机访问文件对象 */
RandomAccessFile randomAccessFile = new RandomAccessFile(
this.saveFile, "rwd");
/** 将文件指针定位到每条线程的 start (即从start位置开始下载)的位置 */
randomAccessFile.seek(start);

/** 打开连接 */
HttpURLConnection httpURLConnection = (HttpURLConnection) (new URL(
this.url)).openConnection();
/** 设置超时 */
httpURLConnection.setConnectTimeout(5000);
/** 设置请求方式 */
httpURLConnection.setRequestMethod("GET");

/** 设置从网络资源文件数据位置从start开始处,到end结束位置的文件数据 */
httpURLConnection.setRequestProperty("Range", "bytes=" + start
+ "-" + end);

/** 如果请求成功,(成功的状态码为206) 则写入本地文件中 */

if (httpURLConnection.getResponseCode() == 206) {
InputStream inputStream = httpURLConnection.getInputStream();
byte[] buffer = new byte[1024];
int length = 0;
while ((length = inputStream.read(buffer)) != -1) {
randomAccessFile.write(buffer, 0, length);
}
System.out.println("第" + this.threadId + "线程下载完毕");

}
} catch (Exception e) {
System.out.println("第" + this.threadId + "线程出错!");
e.printStackTrace();
}

}

/** 获取网络文件资源的文件名 */
public String getFileName() {

/**  如果没有显式设置文件名,则从网络文件资源中设置 */

if ( fileName == null )
{
return url.substring(url.lastIndexOf("/") + 1);
}
return fileName;
}

}


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息