项目结构:
FileDownload.java:
package com.wl.download;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.text.DecimalFormat;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import com.wl.util.DownLoadThread;
import com.wl.util.HttpClientFactory;
public class FileDownload {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
System.out.println(startTime);
String srcFileUrl = "http://172.16.2.40:80/2014/12/gpfqpfvlwsvka2mj39pn.mprx";
String destFilePath = "G:/download/destfile.mprx";
//获取文件的大小
long fileSize = getRemoteFileSize(srcFileUrl);
/**
* 每个线程需要下载的文件大小 (自行调整)
*/
//long unitSize = 1024 ; //多线程太多 卡死你电脑没问题
long unitSize = 1024 * 1024 * 2; //下载文件大小为 = 535.66M; 23559 millisecond
//long unitSize = 1024 * 1024 * 50; //下载文件大小为 = 535.66M; 35726 millisecond
//long unitSize = fileSize; //下载文件大小为 = 535.66M; 所使用时间 = 52865 millisecond
//创建目的文件,并指定大小
createFile(destFilePath, fileSize);
//开几个线程去下载
long threadCount = fileSize / unitSize;
//写入文件的位置
long offset = 0;
if (fileSize <= unitSize) {
// 如果远程文件尺寸小于等于unitSize
DownLoadThread downloadThread = new DownLoadThread(srcFileUrl, destFilePath, offset, fileSize);
Thread t = new Thread(downloadThread);
t.setPriority(10);
t.start();
try {
t.join(); //该方法作用:主线程(此处是 main函数执行的线程) 等待该下载线程结束
} catch (InterruptedException e) {
}
}else{
for (int i = 1; i <= threadCount; i++) {
DownLoadThread downloadThread = new DownLoadThread(
srcFileUrl, destFilePath, offset, unitSize);
Thread t = new Thread(downloadThread);
t.setPriority(10);
t.start();
offset = offset + unitSize;
}
if (fileSize % unitSize != 0) {
// 如果不能整除,则需要再创建一个线程下载剩余字节
DownLoadThread downloadThread = new DownLoadThread(srcFileUrl, destFilePath, offset, fileSize - unitSize * threadCount);
Thread t = new Thread(downloadThread);
t.setPriority(10);
t.start();
try {
t.join(); //该方法作用:主线程(此处是 main函数执行的线程) 等待所有由 主线程产生的下载线程 结束
} catch (InterruptedException e) {
}
}
}
long endTime = System.currentTimeMillis();
System.out.println(endTime);
System.out.println("下载文件大小为 = " + fileSize2String(fileSize)+ "; 所使用时间 = "+ (endTime - startTime) + " millisecond");
}
/**
* 获取文件大小
*/
private static long getRemoteFileSize(String srcFileUrl) {
HttpClient httpClient = HttpClientFactory.getInstance().getHttpClient();
HttpGet httpGet = new HttpGet(srcFileUrl);
// 发送请求,返回响应
HttpResponse response = null;
try {
response = httpClient.execute(httpGet);
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
long result = response.getEntity().getContentLength();
return result;
}
/**
* 创建指定大小的文件
* @param fileName
* @param fileSize
*/
private static void createFile(String fileName, long fileSize) {
File newFile = new File(fileName);
if(newFile.exists())newFile.delete();
RandomAccessFile raf = null;
try {
raf = new RandomAccessFile(newFile, "rw");
raf.setLength(fileSize);
} catch (FileNotFoundException e) {
} catch (IOException e) {
} finally {
try {
if (raf != null) {
raf.close();
}
} catch (IOException e) {
}
}
}
/**
* 获取大小字符串
* @param totalSize
* @return
*/
private static String fileSize2String(long totalSize){
String fileTotalSize="";
DecimalFormat df = new DecimalFormat("0.00");
if(totalSize <1024){
fileTotalSize=totalSize+"B";
}else if(totalSize <1048576){
fileTotalSize=df.format((float)totalSize/1024)+"K";
}else if(totalSize <1073741824){
fileTotalSize=df.format((float)totalSize/1048576)+"M";
}else{
fileTotalSize=df.format((float)totalSize/1073741824)+"G";
}
return fileTotalSize;
}
}
DownLoadThread.java
package com.wl.util;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
public class DownLoadThread implements Runnable {
private String url = null;// 待下载的文件
private String file = null;// 本地存储路径
private long offset = 0;// 偏移量
private long length = 0;// 分配给本线程的下载字节数
public DownLoadThread(String url, String file, long offset, long length) {
this.url = url;
this.file = file;
this.offset = offset;
this.length = length;
}
public void run() {
BufferedInputStream bis = null;
SaveItemFile saveItemFile = null;
try {
HttpURLConnection httpURLConnection = (HttpURLConnection) new URL(
this.url.replace(" ", "%20")).openConnection();
httpURLConnection.setRequestMethod("GET");
httpURLConnection.setRequestProperty("RANGE", "bytes="
+ this.offset + "-" + (this.offset + this.length - 1));
bis = new BufferedInputStream(httpURLConnection.getInputStream());
saveItemFile = new SaveItemFile(file,offset);
byte[] buff = new byte[1024*8];
while ((length = bis.read(buff)) > 0 && offset < offset+length ) {
//写入文件内容,返回最后写入的长度
offset += saveItemFile.write(buff, 0, (int)length);
}
} catch (IOException e) {
} finally {
try {
if (bis != null) {
bis.close();
}
if(saveItemFile!=null){
saveItemFile.close();
}
} catch (IOException e) {
}
}
}
}
HttpClientFactory.java:
package com.wl.util;
import java.util.concurrent.TimeUnit;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
public class HttpClientFactory {
private HttpClient httpClient = null;
/**
* 本类可能存在的惟一的一个实例
*/
private static HttpClientFactory m_instance;
/**
* 静态工厂方法
*
* @return 返还ReadConfigation 类的单一实例
*/
public static HttpClientFactory getInstance() {
if (null == m_instance) {
m_instance = new HttpClientFactory();
}
return m_instance;
}
private HttpClientFactory() {
// 设置组件参数, HTTP协议的版本,1.1/1.0/0.9
HttpParams params = new BasicHttpParams();
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setUserAgent(params, "HttpComponents/1.1");
HttpProtocolParams.setUseExpectContinue(params, true);
// 设置连接超时时间
int REQUEST_TIMEOUT = 30 * 1000; // 设置请求超时10秒钟
int SO_TIMEOUT = 10 * 1000; // 设置等待数据超时时间10秒钟
// HttpConnectionParams.setConnectionTimeout(params, REQUEST_TIMEOUT);
// HttpConnectionParams.setSoTimeout(params, SO_TIMEOUT);
params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,
REQUEST_TIMEOUT);
params.setParameter(CoreConnectionPNames.SO_TIMEOUT, SO_TIMEOUT);
// 设置访问协议
SchemeRegistry schreg = new SchemeRegistry();
schreg.register(new Scheme("http", 80, PlainSocketFactory
.getSocketFactory()));
schreg.register(new Scheme("https", 443, SSLSocketFactory
.getSocketFactory()));
// 多连接的线程安全的管理器
PoolingClientConnectionManager pccm = new PoolingClientConnectionManager(
schreg);
pccm.setDefaultMaxPerRoute(50); // 每个主机的最大并行链接数
pccm.setMaxTotal(100); // 客户端总并行链接最大数
httpClient = new DefaultHttpClient(pccm, params);
httpClient.getConnectionManager().closeIdleConnections(10,
TimeUnit.SECONDS);
}
public DefaultHttpClient getHttpClient() {
return (DefaultHttpClient) httpClient;
}
}
SaveItemFile.java:
package com.wl.util;
import java.io.IOException;
import java.io.RandomAccessFile;
public class SaveItemFile {
//存储文件
private RandomAccessFile itemFile;
public SaveItemFile() throws IOException {
this("", 0);
}
/**
* @param name 文件路径、名称
* @param pos 写入点位置 position
* @throws IOException
*/
public SaveItemFile(String name, long pos) throws IOException {
itemFile = new RandomAccessFile(name, "rw");//可读可写
//在指定的pos位置开始写入数据
itemFile.seek(pos);
}
/**
* <b>function:</b> 同步方法写入文件
* @author hoojo
* @createDate 2011-9-26 下午12:21:22
* @param buff 缓冲数组
* @param start 起始位置
* @param length 长度
* @return
*/
public int write(byte[] buff, int start, int length) {
int i = -1;
try {
itemFile.write(buff, start, length);
i = length;
} catch (IOException e) {
e.printStackTrace();
}
return i;
}
public void close() throws IOException {
if (itemFile != null) {
itemFile.close();
}
}
}
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.filedownload</groupId>
<artifactId>filedownload</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>com.springsource.org.apache.httpcomponents.httpclient</artifactId>
<version>4.2.1</version>
</dependency>
</dependencies>
</project>
over
多线程上传 未完待续........