Main.java
import java.net.HttpURLConnection;
import java.net.URL;
public class Main {
private static Messages messages = new Messages();
private static CallBack callback = new CallBack() {
@Override
public void schedule(Messages messages) {
long totalDownloadSize = messages.getTotalDownloadSize();
int currentDownloadSize = messages.getCurrentDownloadSize();
System.out.println((float)currentDownloadSize * 100.0f / (float)totalDownloadSize + "%");
}
@Override
public void handlerMessages(Messages messages) {
}
@Override
public void fail(Messages messages) {
System.out.println(messages.getMsg());
}
};
public static void main(String[] args) throws Exception {
long startTime = System.currentTimeMillis();
String downloadUrl = "http://www.xiazaiba.com/route.php?ct=stat&ac=stat_ads&id=CG8BOVNg&g=aHR0cDovL3d3dy51aWJpYS5jb20vamttc2V0dXAuZXhl";
URL url = new URL(downloadUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setReadTimeout(1000 * 5);
conn.setRequestProperty("Accept", "image/gif, image/jpeg, image/pjpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml, application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*");
conn.setRequestProperty("Accept-Language", "zh-CN");
conn.setRequestProperty("Referer", downloadUrl);
conn.setRequestProperty("Charset", "UTF-8");
conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.2; Trident/4.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729)");
conn.setRequestProperty("Connection", "Keep-Alive");
conn.connect();
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
FileDownloader loader = new FileDownloader(callback, 4, messages);
int size = conn.getContentLength();//根据响应获取文件大小
loader.setSavePath("E:\\haoya.exe");
loader.setConfigPath("E:\\haoya.properties");
loader.download(downloadUrl, size);
}else{
System.out.println(conn.getResponseCode());
}
conn.disconnect();
long endTime = System.currentTimeMillis();
System.out.println("Time" + (endTime - startTime));
}
}
FileDownloader.java
import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.net.URL;
import java.util.Map;
public class FileDownloader implements DownLoadCallBack {
//单个线程已经下载的长度
private int downloadSize;
//线程数
private DownloadThread[] threads;
// 每条线程下载的长度
private int block;
//文件保存路径
private String savePath;
//配置文件路径
private String configPath;
private File saveFile;
private boolean isNext;
private int call_curr;
private int call_total;
private PropertiesHelper propertiesHelper;
private Map<String, String> datas;
private Messages messages;
private CallBack callback;
//总的下载长度
private int downloadLength;
//是否退出下载
private boolean exit;
public FileDownloader(CallBack callback, int threadNum, Messages messages) {
this.callback = callback;
this.threads = new DownloadThread[threadNum];
this.isNext = false;
this.call_total = threadNum;
this.downloadSize = 0;
this.downloadLength = 0;
this.messages = messages;
this.exit = false;
}
/**
* 开始下载文件
*/
public void download(String downloadUrl, long size){
try {
messages.setTotalDownloadSize(size);
saveFile = new File(savePath);
RandomAccessFile accessFile = new RandomAccessFile(saveFile, "rw");
accessFile.setLength(size);
accessFile.close();
block = (int) ((size % this.threads.length) == 0 ? size
/ this.threads.length : size / this.threads.length + 1);
URL url = new URL(downloadUrl);
propertiesHelper = new PropertiesHelper(configPath);
//如果配置文件不存在,则创建
if(!FileOperate.isFileExist(configPath)){
FileOperate.createFile(configPath, false);
initProperties();
}else{
datas = propertiesHelper.getAllProperties();
if(datas.size() == 0) initProperties();
}
for(int i = 0; i < threads.length; i++){
String value = datas.get(Constant.THREADID + (i + 1));
if(value == null) value = "0";
downloadSize = Integer.parseInt(value);
downloadLength += downloadSize;
}
for (int i = 0; i < threads.length; i++) {// 开启线程进行下载
String value = datas.get(String.valueOf(Constant.THREADID + (i + 1)));
if(value == null) value = "0";
downloadSize = Integer.parseInt(value);
if(downloadSize == block){
call_curr++;
if(call_curr == call_total){
isNext = true;
break;
}
continue;
}
threads[i] = new DownloadThread(url, saveFile, block,
downloadSize, i + 1, messages, callback, this);
threads[i].setPriority(7);
threads[i].start();
}
while(!isNext());
} catch (IOException e) {
messages.setMsg("FileDownloader:download:" + e.getMessage());
callback.fail(messages);
}
}
private synchronized boolean isNext() {
return isNext;
}
private void initProperties() {
for(int i = 0; i < threads.length; i++){
propertiesHelper.setProperties(Constant.THREADID + (i + 1), "0");
}
datas = propertiesHelper.getAllProperties();
}
@Override
public synchronized void isFinished() {
call_curr++;
if (call_curr == call_total){
isNext = true;
}
}
public synchronized void update(String key, String value){
propertiesHelper.setProperties(key, value);
}
@Override
public synchronized int getDownloadLength() {
return downloadLength;
}
@Override
public synchronized void append(int size) {
downloadLength += size;
}
public String getSavePath() {
return savePath;
}
public void setSavePath(String savePath) {
this.savePath = savePath;
}
public String getConfigPath() {
return configPath;
}
public void setConfigPath(String configPath) {
this.configPath = configPath;
}
@Override
public boolean getExit() {
return exit;
}
@Override
public void setExit(boolean isExit) {
exit = isExit;
}
}
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 DownloadThread extends Thread {
private File saveFile;
private URL downUrl;
private int block;
private int threadId = -1;
private CallBack callback;
private DownLoadCallBack downLoadCallBack;
private int downloadSize;
private Messages messages;
public DownloadThread(URL downUrl, File saveFile, int block, int downloadSize, int threadId, Messages messages, CallBack callback, DownLoadCallBack downLoadCallBack) {
this.downLoadCallBack = downLoadCallBack;
this.downUrl = downUrl;
this.saveFile = saveFile;
this.block = block;
this.threadId = threadId;
this.callback = callback;
this.downloadSize = downloadSize;
this.messages = messages;
}
@Override
public void run() {
HttpURLConnection conn = null;
InputStream inStream = null;
RandomAccessFile threadfile = null;
try {
conn = (HttpURLConnection) downUrl.openConnection();
conn.setRequestMethod(Constant.GET);
conn.setReadTimeout(1000 * 8);
int startPos = block * (threadId - 1) + downloadSize;//开始位置
int endPos = block * threadId -1;//结束位置
conn.setRequestProperty("Range", "bytes=" + startPos + "-"+ endPos);//设置获取实体数据的范围
if(conn.getResponseCode() == HttpURLConnection.HTTP_PARTIAL){
inStream = conn.getInputStream();
byte[] buffer = new byte[Constant.BUFFER * 10];
int offset = 0;
threadfile = new RandomAccessFile(saveFile, "rwd");
threadfile.seek(startPos);
String key = Constant.THREADID + String.valueOf(threadId);
//messages,文件总大小,下载的当前大小
while (!downLoadCallBack.getExit() && (offset = inStream.read(buffer)) != -1) {
threadfile.write(buffer, 0, offset);
downLoadCallBack.append(offset);
downloadSize += offset;
downLoadCallBack.update(key, String.valueOf(downloadSize));
int size = downLoadCallBack.getDownloadLength();
messages.setCurrentDownloadSize(size);
callback.schedule(messages);
}
}
} catch (IOException e) {
downLoadCallBack.setExit(true);
messages.setMsg("第" + threadId + "条线程下载失败");
callback.fail(messages);
}finally{
try {
if(threadfile != null){
threadfile.close();
}
if(inStream != null){
inStream.close();
}
if(conn != null){
conn.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
downLoadCallBack.isFinished();
}
}
}
DownLoadCallBack.java
public interface DownLoadCallBack {
public void isFinished();
public void update(String key, String value);
public void append(int size);
public int getDownloadLength();
public boolean getExit();
public void setExit(boolean isExit);
}
CallBack.java
public interface CallBack {
public void handlerMessages(Messages messages);
public void schedule(Messages messages);
public void fail(Messages messages);
}
FileOperate.java
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class FileOperate {
/**
* 在指定路径下创建新文件
* @param filePath 文件路径
* @return
* @throws IOException
*/
public static File createFile(String filePath, boolean isDeleteAllFiles) {
String parentPath = filePath.substring(0, filePath.lastIndexOf(File.separator));
createFolders(parentPath, isDeleteAllFiles);
File file = new File(filePath);
try {
if(!file.createNewFile()){
file.delete();
file.createNewFile();
}
} catch (IOException e) {
e.printStackTrace();
}
return file;
}
/**
* 判断配置文件是否存在
* @param filePath 文件路径
* @return
*/
public static boolean isFileExist(String filePath){
File file = new File(filePath);
return file.exists();
}
/**
* 取得指定目录下的所有文件夹名
* @return
*/
public static List<String> getFilesName(String filePath){
List<String> files_name = null;
File file = new File(filePath);
if(file.exists()){
files_name = new ArrayList<String>();
File[] files = file.listFiles();
for (File file2 : files) {
if(file2.isDirectory()){
files_name.add(file2.getName());
}
}
}
return files_name;
}
public static void deleteFiles(File file){
if(file.exists()){
File[] files = file.listFiles();
for(File f : files){
if(f.isFile()) f.delete();
}
}
}
public static File createFolders(String path, boolean isDeleteAllFiles){
File file = new File(path);
if(file.exists() && file.isDirectory()){
if(isDeleteAllFiles) deleteFiles(file);
}else{
file.mkdirs();
}
return file;
}
public static boolean deleteFile(String filePath){
boolean isDeleted = false;
File file = new File(filePath);
if(file.exists()){
if(file.isFile()) {
file.delete();
isDeleted = true;
}
}
return isDeleted;
}
public static void deleteMkdir(String filePath){
File file = new File(filePath);
if(file.exists() && file.isDirectory()){
file.delete();
}
}
/*********删除文件夹******/
public static boolean deleteFolders(String filePath){
boolean isDeleteSuccess = false;
LinkedList<String> folderList = new LinkedList<String>();
folderList.add(filePath);
while(folderList.size() > 0){
File file1 = new File(folderList.poll());
File[] files1 = file1.listFiles();
ArrayList<File> fileList = new ArrayList<File>();
for(int i = 0; i < fileList.size(); i++){
if(files1[i].isDirectory()){
folderList.add(files1[i].getPath());
}else{
fileList.add(files1[i]);
}
}
//删除文件
for(File file : fileList){
file.delete();
}
}
//删除文件夹
folderList = new LinkedList<String>();
folderList.add(filePath);
while(folderList.size() > 0){
File file2 = new File(folderList.getLast());
if(file2.delete()){
folderList.removeLast();
}else{
File[] files2 = file2.listFiles();
for(int i = 0; i < files2.length; i++){
folderList.add(files2[i].getPath());
}
}
}
if(folderList.size() == 0) isDeleteSuccess = true;
return isDeleteSuccess;
}
public static boolean moveFile(String srcFilePath, String dstFilePath){
boolean isMoveFileSuccess = false;
BufferedInputStream bis = null;
BufferedOutputStream bos = null;
FileInputStream fis = null;
FileOutputStream fos = null;
try {
if(isFileExist(dstFilePath)) deleteFile(dstFilePath);
File dstFile = createFile(dstFilePath, false);
fis = new FileInputStream(new File(srcFilePath));
fos = new FileOutputStream(dstFile);
bis = new BufferedInputStream(fis);
bos = new BufferedOutputStream(fos, Constant.BUFFER * 10);
int count = -1;
byte[] buffer = new byte[Constant.BUFFER * 10];
while((count = bis.read(buffer, 0, Constant.BUFFER * 10)) != -1){
bos.write(buffer, 0, count);
bos.flush();
}
isMoveFileSuccess = true;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(bos != null){
bos.close();
}
if(fos != null){
fos.close();
}
if(bis != null){
bis.close();
}
if(fis != null){
fis.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return isMoveFileSuccess;
}
}
Constant.java
public class Constant {
public static final int BUFFER = 1024;
public static final String UTF = "utf-8";
public static final String THREADID = "threadId";
public static final String OGG = ".ogg";
public static final String PACK = ".pack";
public static final String PNG = ".png";
public static final String MP3 = ".mp3";
public static final String PROPERTIES = ".properties";
public static final String TMX = ".tmx";
public static final String GET = "GET";
}
Messages.java
public class Messages {
private String msg;
private long totalDownloadSize;
private int currentDownloadSize;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public long getTotalDownloadSize() {
return totalDownloadSize;
}
public void setTotalDownloadSize(long totalDownloadSize) {
this.totalDownloadSize = totalDownloadSize;
}
public int getCurrentDownloadSize() {
return currentDownloadSize;
}
public void setCurrentDownloadSize(int currentDownloadSize) {
this.currentDownloadSize = currentDownloadSize;
}
}
PropertiesHelper.java
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
public class PropertiesHelper {
private String project_root = "";
public PropertiesHelper(String filePath) {
if (filePath != null && filePath.length() > 0) {
project_root = project_root + filePath;
}
}
public String getProperties(String key) {
InputStream fis = null;
try {
Properties prop = new Properties();
fis = new FileInputStream(project_root);
prop.load(fis);
return prop.getProperty(key);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fis != null)
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return null;
}
public Map<String, String> getAllProperties() {
InputStream fis = null;
Map<String, String> params = new HashMap<String, String>();
try {
Properties prop = new Properties();
fis = new FileInputStream(project_root);
prop.load(fis);
Enumeration en = prop.propertyNames();
while (en.hasMoreElements()) {
String key = (String) en.nextElement();
String value = prop.getProperty(key);
params.put(key, value);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fis != null)
fis.close();
} catch (Exception e) {
e.printStackTrace();
}
}
return params;
}
public void setProperties(String key, String value) {
Properties prop = new Properties();
FileOutputStream outputFile = null;
InputStream fis = null;
try {
// 输入流和输出流要分开处理, 放一起会造成写入时覆盖以前的属性
fis = new FileInputStream(project_root);
// 先载入已经有的属性文件
prop.load(fis);
// 追加新的属性
prop.setProperty(key, value);
// 写入属性
outputFile = new FileOutputStream(project_root);
prop.store(outputFile, "");
outputFile.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (fis != null)
fis.close();
if (outputFile != null)
outputFile.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}