ftp 单线程实现

pull/330/head
AriaLyy 7 years ago
parent 53128b42dd
commit b987c3fcfa
  1. 2
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java
  2. 25
      Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java
  3. 24
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/ChildThreadConfigEntity.java
  4. 38
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/StateConstance.java
  5. 38
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/ftp/FtpConfigEntity.java
  6. 377
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/ftp/FtpThreadTask.java
  7. 24
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/ChildThreadConfigEntity.java
  8. 12
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/Downloader.java
  9. 68
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/http/HttpThreadTask.java
  10. 22
      Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java

@ -28,7 +28,7 @@ public class DownloadTaskEntity extends AbsTaskEntity<DownloadEntity> {
/** /**
* 账号和密码 * 账号和密码
*/ */
@Ignore public String userName, userPw; @Ignore public String userName, userPw, account;
/** /**
* 下载类型 * 下载类型

@ -18,6 +18,7 @@ package com.arialyy.aria.core.download;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.util.CommonUtil;
/** /**
* Created by lyy on 2016/12/5. * Created by lyy on 2016/12/5.
@ -39,8 +40,10 @@ public class FtpDownloadTarget extends DownloadTarget {
*/ */
private FtpDownloadTarget(String url, String targetName) { private FtpDownloadTarget(String url, String targetName) {
super(url, targetName); super(url, targetName);
int lastIndex = url.lastIndexOf("/");
mTaskEntity.downloadType = AbsTaskEntity.FTP; mTaskEntity.downloadType = AbsTaskEntity.FTP;
mTargetName = targetName; mTargetName = targetName;
mEntity.setFileName(url.substring(lastIndex + 1, url.length()));
} }
/** /**
@ -50,6 +53,17 @@ public class FtpDownloadTarget extends DownloadTarget {
* @param password ftp用户密码 * @param password ftp用户密码
*/ */
public FtpDownloadTarget login(String userName, String password) { public FtpDownloadTarget login(String userName, String password) {
return login(userName, password, null);
}
/**
* ftp 用户登录信息
*
* @param userName ftp用户名
* @param password ftp用户密码
* @param account ftp账号
*/
public FtpDownloadTarget login(String userName, String password, String account) {
if (TextUtils.isEmpty(userName)) { if (TextUtils.isEmpty(userName)) {
Log.e(TAG, "用户名不能为null"); Log.e(TAG, "用户名不能为null");
return this; return this;
@ -59,16 +73,7 @@ public class FtpDownloadTarget extends DownloadTarget {
} }
mTaskEntity.userName = userName; mTaskEntity.userName = userName;
mTaskEntity.userPw = password; mTaskEntity.userPw = password;
return this; mTaskEntity.account = account;
}
/**
* 设置下载的文件
*
* @param filePath ftp服务器上的文件
*/
public FtpDownloadTarget getFile(String filePath) {
return this; return this;
} }
} }

@ -0,0 +1,24 @@
package com.arialyy.aria.core.download.downloader;
import com.arialyy.aria.core.download.DownloadTaskEntity;
import java.io.File;
/**
* 子线程下载信息类
*/
public class ChildThreadConfigEntity {
//线程Id
public int THREAD_ID;
//下载文件大小
public long FILE_SIZE;
//子线程启动下载位置
public long START_LOCATION;
//子线程结束下载位置
public long END_LOCATION;
//下载路径
public File TEMP_FILE;
public String DOWNLOAD_URL;
public String CONFIG_FILE_PATH;
public DownloadTaskEntity DOWNLOAD_TASK_ENTITY;
public boolean IS_SUPPORT_BREAK_POINT = true;
}

@ -13,29 +13,29 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package com.arialyy.aria.core.download.downloader.http; package com.arialyy.aria.core.download.downloader;
/** /**
* Created by lyy on 2017/1/18. * Created by lyy on 2017/1/18.
* 下载状态常量 * 下载状态常量
*/ */
final class StateConstance { public class StateConstance {
int CANCEL_NUM = 0; public int CANCEL_NUM = 0;
int STOP_NUM = 0; public int STOP_NUM = 0;
int FAIL_NUM = 0; public int FAIL_NUM = 0;
int CONNECT_TIME_OUT; //连接超时时间 public int CONNECT_TIME_OUT; //连接超时时间
int READ_TIME_OUT; //流读取的超时时间 public int READ_TIME_OUT; //流读取的超时时间
int COMPLETE_THREAD_NUM = 0; public int COMPLETE_THREAD_NUM = 0;
int THREAD_NUM; public int THREAD_NUM;
long CURRENT_LOCATION = 0; public long CURRENT_LOCATION = 0;
boolean isDownloading = false; public boolean isDownloading = false;
boolean isCancel = false; public boolean isCancel = false;
boolean isStop = false; public boolean isStop = false;
StateConstance() { public StateConstance() {
} }
void cleanState() { public void cleanState() {
isCancel = false; isCancel = false;
isStop = false; isStop = false;
isDownloading = true; isDownloading = true;
@ -48,28 +48,28 @@ final class StateConstance {
/** /**
* 所有子线程是否都已经停止下载 * 所有子线程是否都已经停止下载
*/ */
boolean isStop() { public boolean isStop() {
return STOP_NUM == THREAD_NUM; return STOP_NUM == THREAD_NUM;
} }
/** /**
* 所有子线程是否都已经下载失败 * 所有子线程是否都已经下载失败
*/ */
boolean isFail() { public boolean isFail() {
return FAIL_NUM == THREAD_NUM; return FAIL_NUM == THREAD_NUM;
} }
/** /**
* 所有子线程是否都已经完成下载 * 所有子线程是否都已经完成下载
*/ */
boolean isComplete() { public boolean isComplete() {
return COMPLETE_THREAD_NUM == THREAD_NUM; return COMPLETE_THREAD_NUM == THREAD_NUM;
} }
/** /**
* 所有子线程是否都已经取消下载 * 所有子线程是否都已经取消下载
*/ */
boolean isCancel() { public boolean isCancel() {
return CANCEL_NUM == THREAD_NUM; return CANCEL_NUM == THREAD_NUM;
} }
} }

@ -1,38 +0,0 @@
/*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.core.download.downloader.ftp;
import com.arialyy.aria.core.download.DownloadTaskEntity;
/**
* Created by Aria.Lao on 2017/7/24.
* ftp下载信息实体
*/
class FtpConfigEntity {
//下载文件大小
long FILE_SIZE;
//子线程启动下载位置
long START_LOCATION;
//下载路径
String PATH;
DownloadTaskEntity TASK_ENTITY;
//FTP 服务器地址
String SERVER_IP;
//FTP 服务器端口
String PORT;
//FTP服务器地址
String SERVER_FILE_PATH;
}

@ -1,96 +1,281 @@
///* /*
// * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
// * *
// * Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
// * you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
// * You may obtain a copy of the License at * You may obtain a copy of the License at
// * *
// * http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
// * *
// * Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
// * distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
// * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// * See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
// * limitations under the License. * limitations under the License.
// */ */
//package com.arialyy.aria.core.download.downloader.ftp; package com.arialyy.aria.core.download.downloader.ftp;
//
//import com.arialyy.aria.core.AriaManager; import android.os.Build;
//import com.arialyy.aria.core.download.DownloadTaskEntity; import android.text.TextUtils;
//import com.arialyy.aria.core.download.downloader.IDownloadListener; import android.util.Log;
//import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.core.AriaManager;
//import java.io.File; import com.arialyy.aria.core.download.DownloadEntity;
//import java.io.IOException; import com.arialyy.aria.core.download.DownloadTaskEntity;
//import java.io.InputStream; import com.arialyy.aria.core.download.downloader.ChildThreadConfigEntity;
//import java.math.BigDecimal; import com.arialyy.aria.core.download.downloader.IDownloadListener;
//import org.apache.commons.net.ftp.FTP; import com.arialyy.aria.core.download.downloader.StateConstance;
//import org.apache.commons.net.ftp.FTPClient; import com.arialyy.aria.util.BufferedRandomAccessFile;
//import org.apache.commons.net.ftp.FTPFile; import com.arialyy.aria.util.CommonUtil;
//import org.apache.commons.net.ftp.FTPReply; import java.io.File;
// import java.io.IOException;
///** import java.io.InputStream;
// * Created by Aria.Lao on 2017/7/24. import java.math.BigDecimal;
// * Ftp下载任务 import java.util.Properties;
// */ import org.apache.commons.net.ftp.FTP;
//class FtpThreadTask implements Runnable { import org.apache.commons.net.ftp.FTPClient;
// import org.apache.commons.net.ftp.FTPFile;
// private FtpConfigEntity mConfig; import org.apache.commons.net.ftp.FTPReply;
// private IDownloadListener mListener;
// private DownloadTaskEntity mTaskEntity; /**
// private int mBufSize; * Created by Aria.Lao on 2017/7/24.
// private long mSleepTime = 0; * Ftp下载任务
// */
// FtpThreadTask(FtpConfigEntity config, IDownloadListener listener) { class FtpThreadTask implements Runnable {
// AriaManager manager = AriaManager.getInstance(AriaManager.APP); private final String TAG = "FtpThreadTask";
// mConfig = config; private ChildThreadConfigEntity mConfig;
// mListener = listener; private String mConfigFPath;
// private long mChildCurrentLocation = 0;
// mBufSize = manager.getDownloadConfig().getBuffSize(); private int mBufSize;
// setMaxSpeed(AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getMsxSpeed()); private IDownloadListener mListener;
// } private StateConstance STATE;
// private long mSleepTime = 0;
// void setMaxSpeed(double maxSpeed) { private DownloadTaskEntity mTaskEntity;
// if (-0.9999 < maxSpeed && maxSpeed < 0.00001) { private DownloadEntity mEntity;
// mSleepTime = 0;
// } else { FtpThreadTask(StateConstance constance, IDownloadListener listener,
// BigDecimal db = new BigDecimal(((mBufSize / 1024) / maxSpeed) * 1000); ChildThreadConfigEntity downloadInfo) {
// mSleepTime = db.setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); AriaManager manager = AriaManager.getInstance(AriaManager.APP);
// } STATE = constance;
// } STATE.CONNECT_TIME_OUT = manager.getDownloadConfig().getConnectTimeOut();
// STATE.READ_TIME_OUT = manager.getDownloadConfig().getIOTimeOut();
// @Override public void run() { mListener = listener;
// try { this.mConfig = downloadInfo;
// mConfigFPath = downloadInfo.CONFIG_FILE_PATH;
// FTPClient client = new FTPClient(); mTaskEntity = mConfig.DOWNLOAD_TASK_ENTITY;
// //ip和端口 mEntity = mTaskEntity.getEntity();
// //String[] temp = mEntity.getDownloadUrl().split("/"); mBufSize = manager.getDownloadConfig().getBuffSize();
// //String[] pp = temp[2].split(":"); setMaxSpeed(AriaManager.getInstance(AriaManager.APP).getDownloadConfig().getMsxSpeed());
// String dir = temp[temp.length - 2]; }
// String fileName = temp[temp.length - 1];
// client.connect(pp[0], Integer.parseInt(pp[1])); void setMaxSpeed(double maxSpeed) {
// client.login(mTaskEntity.userName, mTaskEntity.userPw); if (-0.9999 < maxSpeed && maxSpeed < 0.00001) {
// int reply = client.getReplyCode(); mSleepTime = 0;
// if (!FTPReply.isPositiveCompletion(reply)) { } else {
// client.disconnect(); BigDecimal db = new BigDecimal(
// //failDownload("无法连接到ftp服务器,错误码为:" + reply); ((mBufSize / 1024) * (filterVersion() ? 1 : STATE.THREAD_NUM) / maxSpeed) * 1000);
// return; mSleepTime = db.setScale(0, BigDecimal.ROUND_HALF_UP).longValue();
// } }
// client.enterLocalPassiveMode(); }
// client.setFileType(FTP.BINARY_FILE_TYPE);
// FTPFile[] files = client.listFiles(fileName); private boolean filterVersion() {
// files[0].getSize(); return Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
// BufferedRandomAccessFile file = }
// new BufferedRandomAccessFile(new File(mConfig.PATH), "rwd", 8192);
// InputStream is = client.retrieveFileStream(fileName); @Override public void run() {
// FTPClient client = null;
// byte[] buffer = new byte[8192]; InputStream is = null;
// int len; BufferedRandomAccessFile file = null;
// //当前子线程的下载位置 try {
// while ((len = is.read(buffer)) != -1) { Log.d(TAG, "任务【"
// file.write(buffer, 0, len); + mConfig.TEMP_FILE.getName()
// } + "】线程__"
// }catch (IOException e){ + mConfig.THREAD_ID
// + "__开始下载【开始位置 : "
// } + mConfig.START_LOCATION
// } + ",结束位置:"
//} + mConfig.END_LOCATION
+ "】");
client = new FTPClient();
//ip和端口
String[] temp = mEntity.getDownloadUrl().split("/");
String[] pp = temp[2].split(":");
String dir = temp[temp.length - 2];
String fileName = temp[temp.length - 1];
client.connect(pp[0], Integer.parseInt(pp[1]));
if (!TextUtils.isEmpty(mTaskEntity.account)) {
client.login(mTaskEntity.userName, mTaskEntity.userPw);
} else {
client.login(mTaskEntity.userName, mTaskEntity.userPw, mTaskEntity.account);
}
int reply = client.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
client.disconnect();
failDownload(STATE.CURRENT_LOCATION, "无法连接到ftp服务器,错误码为:" + reply, null);
return;
}
client.enterLocalPassiveMode();
client.setFileType(FTP.BINARY_FILE_TYPE);
FTPFile[] files = client.listFiles(fileName);
files[0].getSize();
client.setRestartOffset(mConfig.START_LOCATION);
is = client.retrieveFileStream(fileName);
//创建可设置位置的文件
file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize);
//设置每条线程写入文件的位置
file.seek(mConfig.START_LOCATION);
byte[] buffer = new byte[mBufSize];
int len;
//当前子线程的下载位置
mChildCurrentLocation = mConfig.START_LOCATION;
while ((len = is.read(buffer)) != -1) {
if (STATE.isCancel) break;
if (STATE.isStop) break;
if (mSleepTime > 0) Thread.sleep(mSleepTime);
file.write(buffer, 0, len);
progress(len);
}
if (STATE.isCancel) return;
//停止状态不需要删除记录文件
if (STATE.isStop) return;
//支持断点的处理
if (mConfig.IS_SUPPORT_BREAK_POINT) {
Log.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】线程__" + mConfig.THREAD_ID + "__下载完毕");
writeConfig(true, 1);
STATE.COMPLETE_THREAD_NUM++;
if (STATE.isComplete()) {
File configFile = new File(mConfigFPath);
if (configFile.exists()) {
configFile.delete();
}
STATE.isDownloading = false;
mListener.onComplete();
}
} else {
Log.i(TAG, "下载任务完成");
STATE.isDownloading = false;
mListener.onComplete();
}
} catch (IOException e) {
failDownload(mChildCurrentLocation, "下载失败【" + mConfig.DOWNLOAD_URL + "】", e);
} catch (Exception e) {
failDownload(mChildCurrentLocation, "获取流失败", e);
} finally {
try {
if (file != null) {
file.close();
}
if (is != null) {
is.close();
}
if (client != null) {
client.logout();
client.disconnect();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 停止下载
*/
protected void stop() {
synchronized (AriaManager.LOCK) {
try {
STATE.STOP_NUM++;
Log.d(TAG, "任务【"
+ mConfig.TEMP_FILE.getName()
+ "】thread__"
+ mConfig.THREAD_ID
+ "__停止, stop location ==> "
+ mChildCurrentLocation);
writeConfig(false, mChildCurrentLocation);
if (STATE.isStop()) {
Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已停止");
STATE.isDownloading = false;
mListener.onStop(STATE.CURRENT_LOCATION);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 下载中
*/
private void progress(long len) {
synchronized (AriaManager.LOCK) {
mChildCurrentLocation += len;
STATE.CURRENT_LOCATION += len;
}
}
/**
* 取消下载
*/
protected void cancel() {
synchronized (AriaManager.LOCK) {
STATE.CANCEL_NUM++;
Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】thread__" + mConfig.THREAD_ID + "__取消下载");
if (STATE.isCancel()) {
File configFile = new File(mConfigFPath);
if (configFile.exists()) {
configFile.delete();
}
if (mConfig.TEMP_FILE.exists()) {
mConfig.TEMP_FILE.delete();
}
Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已取消");
STATE.isDownloading = false;
mListener.onCancel();
}
}
}
/**
* 下载失败
*/
private void failDownload(long currentLocation, String msg, Exception ex) {
synchronized (AriaManager.LOCK) {
try {
STATE.FAIL_NUM++;
STATE.isDownloading = false;
STATE.isStop = true;
if (ex != null) {
Log.e(TAG, msg + "\n" + CommonUtil.getPrintException(ex));
}
writeConfig(false, currentLocation);
if (STATE.isFail()) {
Log.e(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】下载失败");
mListener.onFail();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 将记录写入到配置文件
*/
private void writeConfig(boolean isComplete, long record) throws IOException {
synchronized (AriaManager.LOCK) {
String key = null, value = null;
if (0 < record && record < mConfig.END_LOCATION) {
key = mConfig.TEMP_FILE.getName() + "_record_" + mConfig.THREAD_ID;
value = String.valueOf(record);
} else if (record >= mConfig.END_LOCATION || isComplete) {
key = mConfig.TEMP_FILE.getName() + "_state_" + mConfig.THREAD_ID;
value = "1";
}
if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
File configFile = new File(mConfigFPath);
Properties pro = CommonUtil.loadConfig(configFile);
pro.setProperty(key, value);
CommonUtil.saveConfig(configFile, pro);
}
}
}
}

@ -1,24 +0,0 @@
package com.arialyy.aria.core.download.downloader.http;
import com.arialyy.aria.core.download.DownloadTaskEntity;
import java.io.File;
/**
* 子线程下载信息类
*/
final class ChildThreadConfigEntity {
//线程Id
int THREAD_ID;
//下载文件大小
long FILE_SIZE;
//子线程启动下载位置
long START_LOCATION;
//子线程结束下载位置
long END_LOCATION;
//下载路径
File TEMP_FILE;
String DOWNLOAD_URL;
String CONFIG_FILE_PATH;
DownloadTaskEntity DOWNLOAD_TASK_ENTITY;
boolean IS_SUPPORT_BREAK_POINT = true;
}

@ -21,8 +21,10 @@ import android.util.SparseArray;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadTaskEntity; import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.core.download.downloader.ChildThreadConfigEntity;
import com.arialyy.aria.core.download.downloader.IDownloadListener; import com.arialyy.aria.core.download.downloader.IDownloadListener;
import com.arialyy.aria.core.download.downloader.IDownloadUtil; import com.arialyy.aria.core.download.downloader.IDownloadUtil;
import com.arialyy.aria.core.download.downloader.StateConstance;
import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.BufferedRandomAccessFile;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
@ -70,7 +72,7 @@ class Downloader implements Runnable, IDownloadUtil {
@Override @Override
public void setMaxSpeed(double maxSpeed) { public void setMaxSpeed(double maxSpeed) {
for (int i = 0; i < mThreadNum; i++) { for (int i = 0; i < mThreadNum; i++) {
SingleThreadTask task = (SingleThreadTask) mTask.get(i); HttpThreadTask task = (HttpThreadTask) mTask.get(i);
if (task != null) { if (task != null) {
task.setMaxSpeed(maxSpeed); task.setMaxSpeed(maxSpeed);
} }
@ -153,7 +155,7 @@ class Downloader implements Runnable, IDownloadUtil {
mFixedThreadPool.shutdown(); mFixedThreadPool.shutdown();
} }
for (int i = 0; i < mThreadNum; i++) { for (int i = 0; i < mThreadNum; i++) {
SingleThreadTask task = (SingleThreadTask) mTask.get(i); HttpThreadTask task = (HttpThreadTask) mTask.get(i);
if (task != null) { if (task != null) {
task.cancel(); task.cancel();
} }
@ -170,7 +172,7 @@ class Downloader implements Runnable, IDownloadUtil {
mFixedThreadPool.shutdown(); mFixedThreadPool.shutdown();
} }
for (int i = 0; i < mThreadNum; i++) { for (int i = 0; i < mThreadNum; i++) {
SingleThreadTask task = (SingleThreadTask) mTask.get(i); HttpThreadTask task = (HttpThreadTask) mTask.get(i);
if (task != null) { if (task != null) {
task.stop(); task.stop();
} }
@ -294,7 +296,7 @@ class Downloader implements Runnable, IDownloadUtil {
entity.CONFIG_FILE_PATH = mConfigFile.getPath(); entity.CONFIG_FILE_PATH = mConfigFile.getPath();
entity.IS_SUPPORT_BREAK_POINT = mTaskEntity.isSupportBP; entity.IS_SUPPORT_BREAK_POINT = mTaskEntity.isSupportBP;
entity.DOWNLOAD_TASK_ENTITY = mTaskEntity; entity.DOWNLOAD_TASK_ENTITY = mTaskEntity;
SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity); HttpThreadTask task = new HttpThreadTask(mConstance, mListener, entity);
mTask.put(i, task); mTask.put(i, task);
} }
@ -406,7 +408,7 @@ class Downloader implements Runnable, IDownloadUtil {
entity.CONFIG_FILE_PATH = mConfigFile.getPath(); entity.CONFIG_FILE_PATH = mConfigFile.getPath();
entity.IS_SUPPORT_BREAK_POINT = mTaskEntity.isSupportBP; entity.IS_SUPPORT_BREAK_POINT = mTaskEntity.isSupportBP;
entity.DOWNLOAD_TASK_ENTITY = mTaskEntity; entity.DOWNLOAD_TASK_ENTITY = mTaskEntity;
SingleThreadTask task = new SingleThreadTask(mConstance, mListener, entity); HttpThreadTask task = new HttpThreadTask(mConstance, mListener, entity);
mTask.put(0, task); mTask.put(0, task);
mFixedThreadPool.execute(task); mFixedThreadPool.execute(task);
mListener.onPostPre(len); mListener.onPostPre(len);

@ -19,7 +19,9 @@ import android.os.Build;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.downloader.ChildThreadConfigEntity;
import com.arialyy.aria.core.download.downloader.IDownloadListener; import com.arialyy.aria.core.download.downloader.IDownloadListener;
import com.arialyy.aria.core.download.downloader.StateConstance;
import com.arialyy.aria.util.BufferedRandomAccessFile; import com.arialyy.aria.util.BufferedRandomAccessFile;
import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.CommonUtil;
import java.io.File; import java.io.File;
@ -35,22 +37,22 @@ import java.util.Properties;
* Created by lyy on 2017/1/18. * Created by lyy on 2017/1/18.
* 下载线程 * 下载线程
*/ */
final class SingleThreadTask implements Runnable { final class HttpThreadTask implements Runnable {
private static final String TAG = "SingleThreadTask"; private static final String TAG = "HttpThreadTask";
private ChildThreadConfigEntity mConfigEntity; private ChildThreadConfigEntity mConfigEntity;
private String mConfigFPath; private String mConfigFPath;
private long mChildCurrentLocation = 0; private long mChildCurrentLocation = 0;
private int mBufSize; private int mBufSize;
private IDownloadListener mListener; private IDownloadListener mListener;
private StateConstance CONSTANCE; private StateConstance STATE;
private long mSleepTime = 0; private long mSleepTime = 0;
SingleThreadTask(StateConstance constance, IDownloadListener listener, HttpThreadTask(StateConstance constance, IDownloadListener listener,
ChildThreadConfigEntity downloadInfo) { ChildThreadConfigEntity downloadInfo) {
AriaManager manager = AriaManager.getInstance(AriaManager.APP); AriaManager manager = AriaManager.getInstance(AriaManager.APP);
CONSTANCE = constance; STATE = constance;
CONSTANCE.CONNECT_TIME_OUT = manager.getDownloadConfig().getConnectTimeOut(); STATE.CONNECT_TIME_OUT = manager.getDownloadConfig().getConnectTimeOut();
CONSTANCE.READ_TIME_OUT = manager.getDownloadConfig().getIOTimeOut(); STATE.READ_TIME_OUT = manager.getDownloadConfig().getIOTimeOut();
mListener = listener; mListener = listener;
this.mConfigEntity = downloadInfo; this.mConfigEntity = downloadInfo;
if (mConfigEntity.IS_SUPPORT_BREAK_POINT) { if (mConfigEntity.IS_SUPPORT_BREAK_POINT) {
@ -65,7 +67,7 @@ final class SingleThreadTask implements Runnable {
mSleepTime = 0; mSleepTime = 0;
} else { } else {
BigDecimal db = new BigDecimal( BigDecimal db = new BigDecimal(
((mBufSize / 1024) * (filterVersion() ? 1 : CONSTANCE.THREAD_NUM) / maxSpeed) * 1000); ((mBufSize / 1024) * (filterVersion() ? 1 : STATE.THREAD_NUM) / maxSpeed) * 1000);
mSleepTime = db.setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); mSleepTime = db.setScale(0, BigDecimal.ROUND_HALF_UP).longValue();
} }
} }
@ -98,8 +100,8 @@ final class SingleThreadTask implements Runnable {
Log.w(TAG, "该下载不支持断点"); Log.w(TAG, "该下载不支持断点");
} }
conn = ConnectionHelp.setConnectParam(mConfigEntity.DOWNLOAD_TASK_ENTITY, conn); conn = ConnectionHelp.setConnectParam(mConfigEntity.DOWNLOAD_TASK_ENTITY, conn);
conn.setConnectTimeout(CONSTANCE.CONNECT_TIME_OUT); conn.setConnectTimeout(STATE.CONNECT_TIME_OUT);
conn.setReadTimeout(CONSTANCE.READ_TIME_OUT); //设置读取流的等待时间,必须设置该参数 conn.setReadTimeout(STATE.READ_TIME_OUT); //设置读取流的等待时间,必须设置该参数
is = conn.getInputStream(); is = conn.getInputStream();
//创建可设置位置的文件 //创建可设置位置的文件
file = new BufferedRandomAccessFile(mConfigEntity.TEMP_FILE, "rwd", mBufSize); file = new BufferedRandomAccessFile(mConfigEntity.TEMP_FILE, "rwd", mBufSize);
@ -110,15 +112,15 @@ final class SingleThreadTask implements Runnable {
//当前子线程的下载位置 //当前子线程的下载位置
mChildCurrentLocation = mConfigEntity.START_LOCATION; mChildCurrentLocation = mConfigEntity.START_LOCATION;
while ((len = is.read(buffer)) != -1) { while ((len = is.read(buffer)) != -1) {
if (CONSTANCE.isCancel) break; if (STATE.isCancel) break;
if (CONSTANCE.isStop) break; if (STATE.isStop) break;
if (mSleepTime > 0) Thread.sleep(mSleepTime); if (mSleepTime > 0) Thread.sleep(mSleepTime);
file.write(buffer, 0, len); file.write(buffer, 0, len);
progress(len); progress(len);
} }
if (CONSTANCE.isCancel) return; if (STATE.isCancel) return;
//停止状态不需要删除记录文件 //停止状态不需要删除记录文件
if (CONSTANCE.isStop) return; if (STATE.isStop) return;
//支持断点的处理 //支持断点的处理
if (mConfigEntity.IS_SUPPORT_BREAK_POINT) { if (mConfigEntity.IS_SUPPORT_BREAK_POINT) {
Log.i(TAG, "任务【" Log.i(TAG, "任务【"
@ -127,18 +129,18 @@ final class SingleThreadTask implements Runnable {
+ mConfigEntity.THREAD_ID + mConfigEntity.THREAD_ID
+ "__下载完毕"); + "__下载完毕");
writeConfig(true, 1); writeConfig(true, 1);
CONSTANCE.COMPLETE_THREAD_NUM++; STATE.COMPLETE_THREAD_NUM++;
if (CONSTANCE.isComplete()) { if (STATE.isComplete()) {
File configFile = new File(mConfigFPath); File configFile = new File(mConfigFPath);
if (configFile.exists()) { if (configFile.exists()) {
configFile.delete(); configFile.delete();
} }
CONSTANCE.isDownloading = false; STATE.isDownloading = false;
mListener.onComplete(); mListener.onComplete();
} }
} else { } else {
Log.i(TAG, "下载任务完成"); Log.i(TAG, "下载任务完成");
CONSTANCE.isDownloading = false; STATE.isDownloading = false;
mListener.onComplete(); mListener.onComplete();
} }
} catch (MalformedURLException e) { } catch (MalformedURLException e) {
@ -171,7 +173,7 @@ final class SingleThreadTask implements Runnable {
synchronized (AriaManager.LOCK) { synchronized (AriaManager.LOCK) {
try { try {
if (mConfigEntity.IS_SUPPORT_BREAK_POINT) { if (mConfigEntity.IS_SUPPORT_BREAK_POINT) {
CONSTANCE.STOP_NUM++; STATE.STOP_NUM++;
Log.d(TAG, "任务【" Log.d(TAG, "任务【"
+ mConfigEntity.TEMP_FILE.getName() + mConfigEntity.TEMP_FILE.getName()
+ "】thread__" + "】thread__"
@ -179,15 +181,15 @@ final class SingleThreadTask implements Runnable {
+ "__停止, stop location ==> " + "__停止, stop location ==> "
+ mChildCurrentLocation); + mChildCurrentLocation);
writeConfig(false, mChildCurrentLocation); writeConfig(false, mChildCurrentLocation);
if (CONSTANCE.isStop()) { if (STATE.isStop()) {
Log.d(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】已停止"); Log.d(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】已停止");
CONSTANCE.isDownloading = false; STATE.isDownloading = false;
mListener.onStop(CONSTANCE.CURRENT_LOCATION); mListener.onStop(STATE.CURRENT_LOCATION);
} }
} else { } else {
Log.d(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】已停止"); Log.d(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】已停止");
CONSTANCE.isDownloading = false; STATE.isDownloading = false;
mListener.onStop(CONSTANCE.CURRENT_LOCATION); mListener.onStop(STATE.CURRENT_LOCATION);
} }
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
@ -201,7 +203,7 @@ final class SingleThreadTask implements Runnable {
private void progress(long len) { private void progress(long len) {
synchronized (AriaManager.LOCK) { synchronized (AriaManager.LOCK) {
mChildCurrentLocation += len; mChildCurrentLocation += len;
CONSTANCE.CURRENT_LOCATION += len; STATE.CURRENT_LOCATION += len;
} }
} }
@ -211,13 +213,13 @@ final class SingleThreadTask implements Runnable {
protected void cancel() { protected void cancel() {
synchronized (AriaManager.LOCK) { synchronized (AriaManager.LOCK) {
if (mConfigEntity.IS_SUPPORT_BREAK_POINT) { if (mConfigEntity.IS_SUPPORT_BREAK_POINT) {
CONSTANCE.CANCEL_NUM++; STATE.CANCEL_NUM++;
Log.d(TAG, "任务【" Log.d(TAG, "任务【"
+ mConfigEntity.TEMP_FILE.getName() + mConfigEntity.TEMP_FILE.getName()
+ "】thread__" + "】thread__"
+ mConfigEntity.THREAD_ID + mConfigEntity.THREAD_ID
+ "__取消下载"); + "__取消下载");
if (CONSTANCE.isCancel()) { if (STATE.isCancel()) {
File configFile = new File(mConfigFPath); File configFile = new File(mConfigFPath);
if (configFile.exists()) { if (configFile.exists()) {
configFile.delete(); configFile.delete();
@ -226,12 +228,12 @@ final class SingleThreadTask implements Runnable {
mConfigEntity.TEMP_FILE.delete(); mConfigEntity.TEMP_FILE.delete();
} }
Log.d(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】已取消"); Log.d(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】已取消");
CONSTANCE.isDownloading = false; STATE.isDownloading = false;
mListener.onCancel(); mListener.onCancel();
} }
} else { } else {
Log.d(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】已取消"); Log.d(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】已取消");
CONSTANCE.isDownloading = false; STATE.isDownloading = false;
mListener.onCancel(); mListener.onCancel();
} }
} }
@ -243,15 +245,15 @@ final class SingleThreadTask implements Runnable {
private void failDownload(long currentLocation, String msg, Exception ex) { private void failDownload(long currentLocation, String msg, Exception ex) {
synchronized (AriaManager.LOCK) { synchronized (AriaManager.LOCK) {
try { try {
CONSTANCE.FAIL_NUM++; STATE.FAIL_NUM++;
CONSTANCE.isDownloading = false; STATE.isDownloading = false;
CONSTANCE.isStop = true; STATE.isStop = true;
if (ex != null) { if (ex != null) {
Log.e(TAG, msg + "\n" + CommonUtil.getPrintException(ex)); Log.e(TAG, msg + "\n" + CommonUtil.getPrintException(ex));
} }
if (mConfigEntity.IS_SUPPORT_BREAK_POINT) { if (mConfigEntity.IS_SUPPORT_BREAK_POINT) {
writeConfig(false, currentLocation); writeConfig(false, currentLocation);
if (CONSTANCE.isFail()) { if (STATE.isFail()) {
Log.e(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】下载失败"); Log.e(TAG, "任务【" + mConfigEntity.TEMP_FILE.getName() + "】下载失败");
mListener.onFail(); mListener.onFail();
} }

@ -599,6 +599,16 @@ public class CommonUtil {
return err.toString(); return err.toString();
} }
/**
* 通过文件名获取下载配置文件
*
* @param fileName 文件名
*/
public static String getFileConfig(boolean isDownload, String fileName) {
return AriaManager.APP.getFilesDir().getPath() + (isDownload ? AriaManager.DOWNLOAD_TEMP_DIR
: AriaManager.UPLOAD_TEMP_DIR) + fileName + ".properties";
}
/** /**
* 重命名下载配置文件 * 重命名下载配置文件
* 如果旧的配置文件名不存在则使用新的配置文件名新创建一个文件否则将旧的配置文件重命名为新的位置文件名 * 如果旧的配置文件名不存在则使用新的配置文件名新创建一个文件否则将旧的配置文件重命名为新的位置文件名
@ -608,8 +618,7 @@ public class CommonUtil {
* @param newName 新的下载文件名 * @param newName 新的下载文件名
*/ */
public static void renameDownloadConfig(String oldName, String newName) { public static void renameDownloadConfig(String oldName, String newName) {
renameConfig(AriaManager.APP.getFilesDir().getPath() + AriaManager.DOWNLOAD_TEMP_DIR, oldName, renameConfig(true, oldName, newName);
newName);
} }
/** /**
@ -621,14 +630,13 @@ public class CommonUtil {
* @param newName 新的上传文件名 * @param newName 新的上传文件名
*/ */
public static void renameUploadConfig(String oldName, String newName) { public static void renameUploadConfig(String oldName, String newName) {
renameConfig(AriaManager.APP.getFilesDir().getPath() + AriaManager.UPLOAD_TEMP_DIR, oldName, renameConfig(false, oldName, newName);
newName);
} }
private static void renameConfig(String basePath, String oldName, String newName) { private static void renameConfig(boolean isDownload, String oldName, String newName) {
if (oldName.equals(newName)) return; if (oldName.equals(newName)) return;
File oldFile = new File(basePath + oldName + ".properties"); File oldFile = new File(getFileConfig(isDownload, oldName));
File newFile = new File(basePath + newName + ".properties"); File newFile = new File(getFileConfig(isDownload, oldName));
if (!oldFile.exists()) { if (!oldFile.exists()) {
createFile(newFile.getPath()); createFile(newFile.getPath());
} else { } else {

Loading…
Cancel
Save