diff --git a/AppFrame/src/main/java/com/arialyy/frame/util/RegularExpression.java b/AppFrame/src/main/java/com/arialyy/frame/util/RegularExpression.java index 4b405f48..7b05cac8 100644 --- a/AppFrame/src/main/java/com/arialyy/frame/util/RegularExpression.java +++ b/AppFrame/src/main/java/com/arialyy/frame/util/RegularExpression.java @@ -92,5 +92,6 @@ public class RegularExpression { /** * IP */ - public static String IP = "\\d+\\.\\d+\\.\\d+\\.\\d+"; + public static String IP = + "([1-9]|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])(\\.(\\d|[1-9]\\d|1\\d{2}|2[0-4]\\d|25[0-5])){3}"; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/command/ReStartCmd.java b/Aria/src/main/java/com/arialyy/aria/core/command/ReStartCmd.java index 10598993..a2bef76c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/command/ReStartCmd.java +++ b/Aria/src/main/java/com/arialyy/aria/core/command/ReStartCmd.java @@ -15,9 +15,9 @@ */ package com.arialyy.aria.core.command; +import com.arialyy.aria.core.inf.TaskSchedulerType; import com.arialyy.aria.core.task.AbsTask; import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.core.inf.TaskSchedulerType; /** * 重新开始任务命令 @@ -34,8 +34,8 @@ final class ReStartCmd extends AbsNormalCmd { task = createTask(); } if (task != null) { - task.cancel(TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY); - task.start(TaskSchedulerType.TYPE_START_AND_RESET_STATE); + mQueue.cancelTask(task, TaskSchedulerType.TYPE_CANCEL_AND_NOT_NOTIFY); + mQueue.startTask(task, TaskSchedulerType.TYPE_START_AND_RESET_STATE); } } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/AbsNormalTarget.java b/Aria/src/main/java/com/arialyy/aria/core/common/AbsNormalTarget.java index 71a6c789..4920b9a6 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/AbsNormalTarget.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/AbsNormalTarget.java @@ -202,8 +202,8 @@ public abstract class AbsNormalTarget extends Ab * 重新下载 */ @Override - public void reStart() { - getController().reStart(); + public long reStart() { + return getController().reStart(); } @Override diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/FtpOption.java b/Aria/src/main/java/com/arialyy/aria/core/common/FtpOption.java index 168f195e..c162cd83 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/FtpOption.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/FtpOption.java @@ -33,6 +33,9 @@ public class FtpOption extends BaseOption { private String protocol, keyAlias, storePass, storePath; private boolean isImplicit = true; private IFtpUploadInterceptor uploadInterceptor; + private int connMode = FtpConnectionMode.DATA_CONNECTION_MODE_PASV; + private int minPort, maxPort; + private String activeExternalIPAddress; public FtpOption() { super(); @@ -143,6 +146,63 @@ public class FtpOption extends BaseOption { return this; } + /** + * 设置数据传输模式,默认为被动模式。 + * 主动模式:传输文件时,客户端开启一个端口,ftp服务器连接到客户端的该端口,ftp服务器推送数据到客户端 + * 被动模式:传输文件时,ftp服务器开启一个端口,客户端连接到ftp服务器的这个端口,客户端请求ftp服务器的数据 + * 请注意:主动模式是服务器主动连接到android,如果使用住的模式,请确保ftp服务器能ping通android + * + * @param connMode {@link FtpConnectionMode#DATA_CONNECTION_MODE_PASV}, + * {@link FtpConnectionMode#DATA_CONNECTION_MODE_ACTIVITY} + */ + public FtpOption setConnectionMode(int connMode) { + if (connMode != FtpConnectionMode.DATA_CONNECTION_MODE_PASV + && connMode != FtpConnectionMode.DATA_CONNECTION_MODE_ACTIVITY) { + ALog.e(TAG, "连接模式设置失败,默认启用被动模式"); + return this; + } + this.connMode = connMode; + return this; + } + + /** + * 主动模式下的端口范围 + */ + public FtpOption setActivePortRange(int minPort, int maxPort) { + + if (minPort > maxPort) { + ALog.e(TAG, "设置端口范围错误,minPort > maxPort"); + return this; + } + if (minPort <= 0 || minPort >= 65535) { + ALog.e(TAG, "端口范围错误"); + return this; + } + if (maxPort >= 65535) { + ALog.e(TAG, "端口范围错误"); + return this; + } + this.minPort = minPort; + this.maxPort = maxPort; + return this; + } + + /** + * 主动模式下,对外ip(可被Ftp服务器访问的ip) + */ + public FtpOption setActiveExternalIPAddress(String ip) { + if (TextUtils.isEmpty(ip)) { + ALog.e(TAG, "ip为空"); + return this; + } + if (!CheckUtil.checkIp(ip)) { + ALog.e(TAG, "ip地址错误:" + ip); + return this; + } + this.activeExternalIPAddress = ip; + return this; + } + public void setUrlEntity(FtpUrlEntity urlEntity) { this.urlEntity = urlEntity; urlEntity.needLogin = isNeedLogin; diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/controller/BuilderController.java b/Aria/src/main/java/com/arialyy/aria/core/common/controller/BuilderController.java index d66b25a1..70002c01 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/controller/BuilderController.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/controller/BuilderController.java @@ -15,11 +15,10 @@ */ package com.arialyy.aria.core.common.controller; +import com.arialyy.aria.core.command.CmdHelper; import com.arialyy.aria.core.command.NormalCmdFactory; import com.arialyy.aria.core.event.EventMsgUtil; import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.core.command.CmdHelper; -import com.arialyy.aria.util.ALog; /** * 创建任务时使用的控制器 @@ -36,6 +35,7 @@ public final class BuilderController extends FeatureController implements IStart * @return 正常添加,返回任务id,否则返回-1 */ public long add() { + setAction(ACTION_ADD); if (checkConfig()) { EventMsgUtil.getDefault() .post(CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_CREATE, @@ -51,17 +51,18 @@ public final class BuilderController extends FeatureController implements IStart * @return 正常启动,返回任务id,否则返回-1 */ public long create() { + setAction(ACTION_CREATE); if (checkConfig()) { EventMsgUtil.getDefault() .post(CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_START, checkTaskType())); return getEntity().getId(); } - return -1; } @Override public long setHighestPriority() { + setAction(ACTION_PRIORITY); if (checkConfig()) { EventMsgUtil.getDefault() .post(CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_HIGHEST_PRIORITY, diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/controller/FeatureController.java b/Aria/src/main/java/com/arialyy/aria/core/common/controller/FeatureController.java index 875d2ad4..92322853 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/controller/FeatureController.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/controller/FeatureController.java @@ -43,6 +43,17 @@ import java.lang.reflect.InvocationTargetException; * 功能控制器 */ public abstract class FeatureController { + private static final int ACTION_DEF = 0; + public static final int ACTION_CREATE = 1; + public static final int ACTION_RESUME = 2; + public static final int ACTION_STOP = 3; + public static final int ACTION_CANCEL = 4; + public static final int ACTION_ADD = 5; + public static final int ACTION_PRIORITY = 6; + public static final int ACTION_RETRY = 7; + public static final int ACTION_RESTART = 8; + public static final int ACTION_SAVE = 9; + private final String TAG; private AbsTaskWrapper mTaskWrapper; @@ -50,6 +61,7 @@ public abstract class FeatureController { * 是否忽略权限检查 true 忽略权限检查 */ private boolean ignoreCheckPermissions = false; + private int action = ACTION_DEF; FeatureController(AbsTaskWrapper wrapper) { mTaskWrapper = wrapper; @@ -91,6 +103,10 @@ public abstract class FeatureController { return null; } + void setAction(int action) { + this.action = action; + } + /** * 是否忽略权限检查 */ @@ -180,15 +196,15 @@ public abstract class FeatureController { private boolean checkEntity() { ICheckEntityUtil checkUtil = null; if (mTaskWrapper instanceof DTaskWrapper) { - checkUtil = CheckDEntityUtil.newInstance((DTaskWrapper) mTaskWrapper); + checkUtil = CheckDEntityUtil.newInstance((DTaskWrapper) mTaskWrapper, action); } else if (mTaskWrapper instanceof DGTaskWrapper) { if (mTaskWrapper.getRequestType() == ITaskWrapper.D_FTP_DIR) { - checkUtil = CheckFtpDirEntityUtil.newInstance((DGTaskWrapper) mTaskWrapper); + checkUtil = CheckFtpDirEntityUtil.newInstance((DGTaskWrapper) mTaskWrapper, action); } else if (mTaskWrapper.getRequestType() == ITaskWrapper.DG_HTTP) { - checkUtil = CheckDGEntityUtil.newInstance((DGTaskWrapper) mTaskWrapper); + checkUtil = CheckDGEntityUtil.newInstance((DGTaskWrapper) mTaskWrapper, action); } } else if (mTaskWrapper instanceof UTaskWrapper) { - checkUtil = CheckUEntityUtil.newInstance((UTaskWrapper) mTaskWrapper); + checkUtil = CheckUEntityUtil.newInstance((UTaskWrapper) mTaskWrapper, action); } return checkUtil != null && checkUtil.checkEntity(); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/controller/INormalFeature.java b/Aria/src/main/java/com/arialyy/aria/core/common/controller/INormalFeature.java index 968098fd..3808e1ba 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/controller/INormalFeature.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/controller/INormalFeature.java @@ -59,7 +59,7 @@ public interface INormalFeature { /** * 重新下载 */ - void reStart(); + long reStart(); /** * 保存数据 diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/controller/NormalController.java b/Aria/src/main/java/com/arialyy/aria/core/common/controller/NormalController.java index 8d019d01..f1c18a22 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/controller/NormalController.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/controller/NormalController.java @@ -38,6 +38,7 @@ public final class NormalController extends FeatureController implements INormal */ @Override public void stop() { + setAction(ACTION_STOP); if (checkConfig()) { EventMsgUtil.getDefault() .post(CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_STOP, @@ -60,6 +61,7 @@ public final class NormalController extends FeatureController implements INormal * @param newStart true 立即将任务恢复到执行队列中 */ @Override public void resume(boolean newStart) { + setAction(ACTION_RESUME); if (checkConfig()) { StartCmd cmd = (StartCmd) CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_START, @@ -75,11 +77,7 @@ public final class NormalController extends FeatureController implements INormal */ @Override public void cancel() { - if (checkConfig()) { - EventMsgUtil.getDefault() - .post(CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_CANCEL, - checkTaskType())); - } + cancel(false); } /** @@ -87,6 +85,7 @@ public final class NormalController extends FeatureController implements INormal */ @Override public void reTry() { + setAction(ACTION_RETRY); if (checkConfig()) { int taskType = checkTaskType(); EventMsgUtil.getDefault() @@ -105,6 +104,7 @@ public final class NormalController extends FeatureController implements INormal */ @Override public void cancel(boolean removeFile) { + setAction(ACTION_CANCEL); if (checkConfig()) { CancelCmd cancelCmd = (CancelCmd) CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_CANCEL, @@ -118,15 +118,19 @@ public final class NormalController extends FeatureController implements INormal * 重新下载 */ @Override - public void reStart() { + public long reStart() { + setAction(ACTION_RESTART); if (checkConfig()) { EventMsgUtil.getDefault() .post(CmdHelper.createNormalCmd(getTaskWrapper(), NormalCmdFactory.TASK_RESTART, checkTaskType())); + return getEntity().getId(); } + return -1; } @Override public void save() { + setAction(ACTION_SAVE); if (!checkConfig()) { ALog.e(TAG, "保存修改失败"); } else { diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/CheckDEntityUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/CheckDEntityUtil.java index 163af4ee..3bf9bfef 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/CheckDEntityUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/CheckDEntityUtil.java @@ -16,6 +16,7 @@ package com.arialyy.aria.core.download; import android.text.TextUtils; +import com.arialyy.aria.core.common.controller.FeatureController; import com.arialyy.aria.core.inf.ICheckEntityUtil; import com.arialyy.aria.core.inf.IOptionConstant; import com.arialyy.aria.core.inf.ITargetHandler; @@ -34,12 +35,14 @@ public class CheckDEntityUtil implements ICheckEntityUtil { private final String TAG = CommonUtil.getClassName(getClass()); private DTaskWrapper mWrapper; private DownloadEntity mEntity; + private int action; - public static CheckDEntityUtil newInstance(DTaskWrapper wrapper) { - return new CheckDEntityUtil(wrapper); + public static CheckDEntityUtil newInstance(DTaskWrapper wrapper, int action) { + return new CheckDEntityUtil(wrapper, action); } - private CheckDEntityUtil(DTaskWrapper wrapper) { + private CheckDEntityUtil(DTaskWrapper wrapper, int action) { + this.action = action; mWrapper = wrapper; mEntity = mWrapper.getEntity(); } @@ -80,19 +83,22 @@ public class CheckDEntityUtil implements ICheckEntityUtil { } else { m3U8Entity.update(); } - if (mWrapper.getRequestType() == ITaskWrapper.M3U8_VOD) { + if (mWrapper.getRequestType() == ITaskWrapper.M3U8_VOD + && action == FeatureController.ACTION_CREATE) { if (mEntity.getFileSize() == 0) { ALog.w(TAG, "由于m3u8协议的特殊性质,无法有效快速获取到正确到文件长度,如果你需要显示文件中长度,你需要自行设置文件长度:.asM3U8().asVod().setFileSize(xxx)"); } - } else if (mWrapper.getRequestType() == ITaskWrapper.M3U8_LIVE) { + } else if (mWrapper.getRequestType() == ITaskWrapper.M3U8_LIVE + && action != FeatureController.ACTION_CANCEL) { if (file.exists()) { ALog.w(TAG, "对于直播来说,每次下载都是一个新文件,所以你需要设置新都文件路径,否则Aria框架将会覆盖已下载的文件"); file.delete(); } } - if (mWrapper.getM3U8Params().getHandler(IOptionConstant.bandWidthUrlConverter) != null + if (action != FeatureController.ACTION_CANCEL + && mWrapper.getM3U8Params().getHandler(IOptionConstant.bandWidthUrlConverter) != null && bandWidth == 0) { ALog.w(TAG, "你已经设置了码率url转换器,但是没有设置码率,Aria框架将采用第一个获取到的码率"); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/CheckDGEntityUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/CheckDGEntityUtil.java index 0e854888..1bf6b387 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/CheckDGEntityUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/CheckDGEntityUtil.java @@ -17,6 +17,7 @@ package com.arialyy.aria.core.download; import android.text.TextUtils; import com.arialyy.aria.core.common.RequestEnum; +import com.arialyy.aria.core.common.controller.FeatureController; import com.arialyy.aria.core.inf.ICheckEntityUtil; import com.arialyy.aria.core.inf.IOptionConstant; import com.arialyy.aria.orm.DbEntity; @@ -41,12 +42,14 @@ public class CheckDGEntityUtil implements ICheckEntityUtil { * 是否需要修改路径 */ private boolean needModifyPath = false; + private int action; - public static CheckDGEntityUtil newInstance(DGTaskWrapper wrapper) { - return new CheckDGEntityUtil(wrapper); + public static CheckDGEntityUtil newInstance(DGTaskWrapper wrapper, int action) { + return new CheckDGEntityUtil(wrapper, action); } - private CheckDGEntityUtil(DGTaskWrapper wrapper) { + private CheckDGEntityUtil(DGTaskWrapper wrapper, int action) { + this.action = action; mWrapper = wrapper; mEntity = mWrapper.getEntity(); } @@ -129,7 +132,9 @@ public class CheckDGEntityUtil implements ICheckEntityUtil { return false; } - if (!mWrapper.isUnknownSize() && mEntity.getFileSize() == 0) { + if (action != FeatureController.ACTION_CANCEL + && !mWrapper.isUnknownSize() + && mEntity.getFileSize() == 0) { ALog.e(TAG, "组合任务必须设置文件文件大小,默认需要强制设置文件大小。如果无法获取到总长度,请调用#unknownSize()来标志该组合任务"); return false; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/CheckFtpDirEntityUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/CheckFtpDirEntityUtil.java index 8f1cdf88..b46da62a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/CheckFtpDirEntityUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/CheckFtpDirEntityUtil.java @@ -17,7 +17,6 @@ package com.arialyy.aria.core.download; import android.text.TextUtils; import com.arialyy.aria.core.FtpUrlEntity; -import com.arialyy.aria.core.common.ErrorCode; import com.arialyy.aria.core.inf.ICheckEntityUtil; import com.arialyy.aria.core.inf.IOptionConstant; import com.arialyy.aria.orm.DbEntity; @@ -28,12 +27,14 @@ public class CheckFtpDirEntityUtil implements ICheckEntityUtil { private final String TAG = "CheckFtpDirEntityUtil"; private DGTaskWrapper mWrapper; private DownloadGroupEntity mEntity; + private int action; - public static CheckFtpDirEntityUtil newInstance(DGTaskWrapper wrapper) { - return new CheckFtpDirEntityUtil(wrapper); + public static CheckFtpDirEntityUtil newInstance(DGTaskWrapper wrapper, int action) { + return new CheckFtpDirEntityUtil(wrapper, action); } - private CheckFtpDirEntityUtil(DGTaskWrapper wrapper) { + private CheckFtpDirEntityUtil(DGTaskWrapper wrapper, int action) { + this.action = action; mWrapper = wrapper; mEntity = mWrapper.getEntity(); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java b/Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java index fe6dcfcf..ea3c768a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java +++ b/Aria/src/main/java/com/arialyy/aria/core/queue/AbsTaskQueue.java @@ -16,10 +16,6 @@ package com.arialyy.aria.core.queue; -import com.arialyy.aria.core.task.DownloadGroupTask; -import com.arialyy.aria.core.task.DownloadTask; -import com.arialyy.aria.core.task.AbsTask; -import com.arialyy.aria.core.wrapper.AbsTaskWrapper; import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.inf.TaskSchedulerType; import com.arialyy.aria.core.manager.TaskWrapperManager; @@ -29,7 +25,11 @@ import com.arialyy.aria.core.queue.pool.BaseExecutePool; import com.arialyy.aria.core.queue.pool.DGLoadSharePool; import com.arialyy.aria.core.queue.pool.DLoadSharePool; import com.arialyy.aria.core.queue.pool.UploadSharePool; +import com.arialyy.aria.core.task.AbsTask; +import com.arialyy.aria.core.task.DownloadGroupTask; +import com.arialyy.aria.core.task.DownloadTask; import com.arialyy.aria.core.task.UploadTask; +import com.arialyy.aria.core.wrapper.AbsTaskWrapper; import com.arialyy.aria.util.ALog; /** @@ -213,6 +213,10 @@ public abstract class AbsTaskQueue 0) { - client = newInstanceClient(urlEntity); - client.setConnectTimeout(mConnectTimeOut); // 连接10s超时 - InetAddress ip = InetAddress.getByName(urlEntity.hostName); - - client = connect(client, new InetAddress[] { ip }, 0, Integer.parseInt(urlEntity.port)); - mTaskOption.getUrlEntity().validAddr = ip; - } else { - DNSQueryThread dnsThread = new DNSQueryThread(urlEntity.hostName); - dnsThread.start(); - dnsThread.join(mConnectTimeOut); - InetAddress[] ips = dnsThread.getIps(); - client = connect(newInstanceClient(urlEntity), ips, 0, Integer.parseInt(urlEntity.port)); - } + if (CheckUtil.checkIp(urlEntity.hostName)) { + client = newInstanceClient(urlEntity); + client.setConnectTimeout(mConnectTimeOut); // 连接10s超时 + InetAddress ip = InetAddress.getByName(urlEntity.hostName); - if (client == null) { - failDownload(new AriaIOException(TAG, - String.format("链接失败, url: %s", mTaskOption.getUrlEntity().url)), false); - return null; - } + client = connect(client, new InetAddress[] { ip }, 0, Integer.parseInt(urlEntity.port)); + mTaskOption.getUrlEntity().validAddr = ip; + } else { + DNSQueryThread dnsThread = new DNSQueryThread(urlEntity.hostName); + dnsThread.start(); + dnsThread.join(mConnectTimeOut); + InetAddress[] ips = dnsThread.getIps(); + client = connect(newInstanceClient(urlEntity), ips, 0, Integer.parseInt(urlEntity.port)); + } - boolean loginSuccess = true; - if (urlEntity.needLogin) { - try { - if (TextUtils.isEmpty(urlEntity.account)) { - loginSuccess = client.login(urlEntity.user, urlEntity.password); - } else { - loginSuccess = client.login(urlEntity.user, urlEntity.password, urlEntity.account); - } - } catch (IOException e) { - ALog.e(TAG, - new TaskException(TAG, String.format("登录失败,错误码为:%s, msg:%s", client.getReplyCode(), - client.getReplyString()), e)); - return null; - } - } + if (client == null) { + failDownload(client, String.format("链接失败, url: %s", mTaskOption.getUrlEntity().url), null, + true); + return null; + } - if (!loginSuccess) { - failDownload( + boolean loginSuccess = true; + if (urlEntity.needLogin) { + try { + if (TextUtils.isEmpty(urlEntity.account)) { + loginSuccess = client.login(urlEntity.user, urlEntity.password); + } else { + loginSuccess = client.login(urlEntity.user, urlEntity.password, urlEntity.account); + } + } catch (IOException e) { + ALog.e(TAG, new TaskException(TAG, String.format("登录失败,错误码为:%s, msg:%s", client.getReplyCode(), - client.getReplyString())), - false); - client.disconnect(); + client.getReplyString()), e)); return null; } + } - int reply = client.getReplyCode(); - if (!FTPReply.isPositiveCompletion(reply)) { - client.disconnect(); - failDownload(new AriaIOException(TAG, - String.format("无法连接到ftp服务器,filePath: %s, url: %s, errorCode: %s, errorMsg:%s", - mEntity.getKey(), mTaskOption.getUrlEntity().url, reply, - client.getReplyString())), - true); - return null; + if (!loginSuccess) { + failDownload(client, "登录失败", null, false); + client.disconnect(); + return null; + } + + int reply = client.getReplyCode(); + if (!FTPReply.isPositiveCompletion(reply)) { + failDownload(client, String.format("无法连接到ftp服务器,filePath: %s, url: %s", mEntity.getKey(), + mTaskOption.getUrlEntity().url), null, true); + client.disconnect(); + return null; + } + // 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码 + charSet = "UTF-8"; + reply = client.sendCommand("OPTS UTF8", "ON"); + if (reply != FTPReply.COMMAND_IS_SUPERFLUOUS) { + ALog.i(TAG, "D_FTP 服务器不支持开启UTF8编码,尝试使用Aria手动设置的编码"); + if (!TextUtils.isEmpty(mTaskOption.getCharSet())) { + charSet = mTaskOption.getCharSet(); } - // 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码 - charSet = "UTF-8"; - reply = client.sendCommand("OPTS UTF8", "ON"); - if (reply != FTPReply.COMMAND_IS_SUPERFLUOUS) { - ALog.i(TAG, "D_FTP 服务器不支持开启UTF8编码,尝试使用Aria手动设置的编码"); - if (!TextUtils.isEmpty(mTaskOption.getCharSet())) { - charSet = mTaskOption.getCharSet(); - } + } + client.setControlEncoding(charSet); + client.setDataTimeout(10 * 1000); + if (mTaskOption.getConnMode() == FtpConnectionMode.DATA_CONNECTION_MODE_ACTIVITY) { + client.enterLocalActiveMode(); + if (mTaskOption.getMinPort() != 0 && mTaskOption.getMaxPort() != 0) { + client.setActivePortRange(mTaskOption.getMinPort(), mTaskOption.getMaxPort()); + } + if (!TextUtils.isEmpty(mTaskOption.getActiveExternalIPAddress())) { + client.setActiveExternalIPAddress(mTaskOption.getActiveExternalIPAddress()); } - client.setControlEncoding(charSet); - client.setDataTimeout(10 * 1000); + } else { client.enterLocalPassiveMode(); - client.setFileType(FTP.BINARY_FILE_TYPE); - } catch (IOException e) { - closeClient(client); - e.printStackTrace(); - } catch (InterruptedException e) { - closeClient(client); - e.printStackTrace(); } + client.setFileType(FTP.BINARY_FILE_TYPE); + return client; } @@ -387,9 +379,19 @@ public abstract class AbsFtpInfoThread 15) { + return false; + } + Pattern p = Pattern.compile(Regular.REG_IP_V4); + Matcher m = p.matcher(ip); + return m.find() && m.groupCount() > 0; + } + + /** + * 判断http请求是否有效 + * {@link HttpURLConnection#HTTP_BAD_GATEWAY} or {@link HttpURLConnection#HTTP_BAD_METHOD} + * or {@link HttpURLConnection#HTTP_BAD_REQUEST} 无法重试 + * + * @param errorCode http 返回码 + * @return {@code true} 无效请求;{@code false} 有效请求 + */ + public static boolean httpIsBadRequest(int errorCode) { + return errorCode == HttpURLConnection.HTTP_BAD_GATEWAY + || errorCode == HttpURLConnection.HTTP_BAD_METHOD + || errorCode == HttpURLConnection.HTTP_BAD_REQUEST; + } + + /** + * 判断ftp请求是否有效 + * + * @return {@code true} 无效请求;{@code false} 有效请求 + */ + public static boolean ftpIsBadRequest(int errorCode) { + return errorCode >= 400 && errorCode < 600; + } + /** * 检查和处理下载任务的路径冲突 * diff --git a/app/src/main/java/com/arialyy/simple/core/download/FtpDownloadActivity.java b/app/src/main/java/com/arialyy/simple/core/download/FtpDownloadActivity.java index f1c4cef1..8efca66d 100644 --- a/app/src/main/java/com/arialyy/simple/core/download/FtpDownloadActivity.java +++ b/app/src/main/java/com/arialyy/simple/core/download/FtpDownloadActivity.java @@ -23,6 +23,7 @@ import androidx.lifecycle.Observer; import androidx.lifecycle.ViewModelProviders; import com.arialyy.annotations.Download; import com.arialyy.aria.core.Aria; +import com.arialyy.aria.core.common.FtpConnectionMode; import com.arialyy.aria.core.common.FtpOption; import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.inf.IEntity; @@ -80,11 +81,11 @@ public class FtpDownloadActivity extends BaseActivity getFtpDownloadInfo(Context context) { - String url = AppUtil.getConfigValue(context, FTP_URL_KEY, ftpDefUrl); + //String url = AppUtil.getConfigValue(context, FTP_URL_KEY, ftpDefUrl); + String url = "ftp://9.9.9.72:2121/Cyberduck-6.9.4.30164.zip"; String filePath = AppUtil.getConfigValue(context, FTP_PATH_KEY, ftpDefPath); singDownloadInfo = Aria.download(context).getFirstDownloadEntity(url); diff --git a/app/src/main/java/com/arialyy/simple/core/download/HttpDownloadModule.java b/app/src/main/java/com/arialyy/simple/core/download/HttpDownloadModule.java index aad5bc82..869febdc 100644 --- a/app/src/main/java/com/arialyy/simple/core/download/HttpDownloadModule.java +++ b/app/src/main/java/com/arialyy/simple/core/download/HttpDownloadModule.java @@ -54,11 +54,12 @@ public class HttpDownloadModule extends BaseViewModule { //String url = "http://image.totwoo.com/totwoo-TOTWOO-v3.5.6.apk"; //String url = "http://fdfs.speedata.cn:9989/group1/M00/00/05/rBGFrl3fdAKAVJwfMtSa9R18wLU139.zip"; //String url = "http://9.9.9.28:8088/files/update.zip"; - String url = "https://ss1.baidu.com/-4o3dSag_xI4khGko9WTAnF6hhy/image/h%3D300/sign=a9e671b9a551f3dedcb2bf64a4eff0ec/4610b912c8fcc3cef70d70409845d688d53f20f7.jpg"; + //String url = "https://ss1.baidu.com/-4o3dSag_xI4khGko9WTAnF6hhy/image/h%3D300/sign=a9e671b9a551f3dedcb2bf64a4eff0ec/4610b912c8fcc3cef70d70409845d688d53f20f7.jpg"; //String url = "https://imtt.dd.qq.com/16891/apk/70BFFDB05AB8686F2A4CF3E07588A377.apk?fsname=com.tencent.tmgp.speedmobile_1.16.0.33877_1160033877.apk&csr=1bbd"; //String url = "https://ss1.baidu.com/-4o3dSag_xI4khGko9WTAnF6hhy/image/h%3D300/sign=a9e671b9a551f3dedcb2bf64a4eff0ec/4610b912c8fcc3cef70d70409845d688d53f20f7.jpg"; //String filePath = AppUtil.getConfigValue(context, HTTP_PATH_KEY, defFilePath); - String filePath = "/mnt/sdcard/gg.png"; + String url = "https://y.qq.com/download/import/QQMusic-import-1.2.1.zip"; + String filePath = "/mnt/sdcard/QQMusic-import-1.2.1.zip"; //String filePath = "/mnt/sdcard/update.zip"; singDownloadInfo = Aria.download(context).getFirstDownloadEntity(url); diff --git a/app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java b/app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java index d72aa415..c6b238f6 100644 --- a/app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java +++ b/app/src/main/java/com/arialyy/simple/core/download/SingleTaskActivity.java @@ -32,6 +32,7 @@ import androidx.lifecycle.ViewModelProviders; import com.arialyy.annotations.Download; import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.common.HttpOption; +import com.arialyy.aria.core.common.RequestEnum; import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.inf.IEntity; import com.arialyy.aria.core.listener.ISchedulers; @@ -116,11 +117,6 @@ public class SingleTaskActivity extends BaseActivity { } }); getBinding().setViewModel(this); - try { - getBinding().codeView.setSource(AppUtil.getHelpCode(this, "HttpDownload.java")); - } catch (IOException e) { - e.printStackTrace(); - } } public void chooseUrl() { @@ -279,10 +275,9 @@ public class SingleTaskActivity extends BaseActivity { .load(mTaskId) .stop(); } else { - mUrl = "http://sdkdown.muzhiwan.com/openfile/2019/07/11/com.netease.syfz.mzw_5d26f8d9cee27.apk"; - Aria.download(this).load(mTaskId) + mTaskId = Aria.download(this).load(mTaskId) //.updateUrl(mUrl) - .resume(); + .reStart(); } break; case R.id.cancel: @@ -296,6 +291,7 @@ public class SingleTaskActivity extends BaseActivity { option.addHeader("1", "@") .useServerFileName(true) .setFileLenAdapter(new FileLenAdapter()); + //option.setRequestType(RequestEnum.POST); mTaskId = Aria.download(SingleTaskActivity.this) .load(mUrl) .setFilePath(mFilePath, true) diff --git a/app/src/main/java/com/arialyy/simple/core/download/mutil/DownloadAdapter.java b/app/src/main/java/com/arialyy/simple/core/download/mutil/DownloadAdapter.java index 0e90f9a5..4d099c82 100644 --- a/app/src/main/java/com/arialyy/simple/core/download/mutil/DownloadAdapter.java +++ b/app/src/main/java/com/arialyy/simple/core/download/mutil/DownloadAdapter.java @@ -298,7 +298,7 @@ public class DownloadAdapter extends AbsRVAdapter - + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_single.xml b/app/src/main/res/layout/activity_single.xml index 7716da64..0b679ab9 100644 --- a/app/src/main/res/layout/activity_single.xml +++ b/app/src/main/res/layout/activity_single.xml @@ -76,11 +76,5 @@ bind:stateStr="@{stateStr}" /> - - \ No newline at end of file