修复组合任务初始化失败时,无法删除的问题

修复`reStart()`后,无法停止的问题
ftp增加主动模式,开启主动模式:https://aria.laoyuyu.me/aria_doc/api/ftp_params.html
优化提示
This commit is contained in:
laoyuyu
2019-12-16 20:18:45 +08:00
parent f3d5e0135a
commit 0d93953cd9
33 changed files with 446 additions and 197 deletions

View File

@@ -27,24 +27,21 @@ import aria.apache.commons.net.ftp.FTPSClient;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.AbsEntity;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.common.FtpConnectionMode;
import com.arialyy.aria.core.inf.OnFileInfoCallback;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.exception.AriaIOException;
import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.exception.FileNotFoundException;
import com.arialyy.aria.exception.TaskException;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.Regular;
import com.arialyy.aria.util.SSLContextUtil;
import java.io.File;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.net.ssl.SSLContext;
/**
@@ -117,9 +114,9 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
}
closeClient(client);
failDownload(new FileNotFoundException(TAG,
failDownload(client,
String.format("文件不存在url: %s, remotePath%s", mTaskOption.getUrlEntity().url,
remotePath)), false);
remotePath), null, false);
return;
}
@@ -139,9 +136,7 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
mTaskWrapper.setNewTask(true);
} else {
closeClient(client);
failDownload(new AriaIOException(TAG,
String.format("获取文件信息错误url: %s, errorCode%s, errorMsg%s",
mTaskOption.getUrlEntity().url, reply, client.getReplyString())), true);
failDownload(client, "获取文件信息错误url: " + mTaskOption.getUrlEntity().url, null, true);
return;
}
}
@@ -152,9 +147,11 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
onPreComplete(reply);
mEntity.update();
} catch (IOException e) {
failDownload(new AriaIOException(TAG,
String.format("FTP错误信息code%smsg%s", client.getReplyCode(), client.getReplyString()),
e), true);
e.printStackTrace();
failDownload(client, "FTP错误信息", e, true);
} catch (InterruptedException e) {
e.printStackTrace();
failDownload(client, "FTP错误信息", e, true);
} finally {
closeClient(client);
}
@@ -191,88 +188,83 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
/**
* 创建FTP客户端
*/
private FTPClient createFtpClient() {
private FTPClient createFtpClient() throws IOException, InterruptedException {
FTPClient client = null;
final FtpUrlEntity urlEntity = mTaskOption.getUrlEntity();
try {
Pattern p = Pattern.compile(Regular.REG_IP_V4);
Matcher m = p.matcher(urlEntity.hostName);
if (m.find() && m.groupCount() > 0) {
client = newInstanceClient(urlEntity);
client.setConnectTimeout(mConnectTimeOut); // 连接10s超时
InetAddress ip = InetAddress.getByName(urlEntity.hostName);
if (CheckUtil.checkIp(urlEntity.hostName)) {
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 (client == null) {
failDownload(new AriaIOException(TAG,
String.format("链接失败, url: %s", mTaskOption.getUrlEntity().url)), false);
return null;
}
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 (!loginSuccess) {
failDownload(
new TaskException(TAG, String.format("登录失败,错误码为:%s msg%s", client.getReplyCode(),
client.getReplyString())),
false);
client.disconnect();
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;
}
// 开启服务器对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);
client.enterLocalPassiveMode();
client.setFileType(FTP.BINARY_FILE_TYPE);
} catch (IOException e) {
closeClient(client);
e.printStackTrace();
} catch (InterruptedException e) {
closeClient(client);
e.printStackTrace();
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 (client == null) {
failDownload(client, String.format("链接失败, url: %s", mTaskOption.getUrlEntity().url), null,
true);
return null;
}
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 (!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();
}
}
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());
}
} else {
client.enterLocalPassiveMode();
}
client.setFileType(FTP.BINARY_FILE_TYPE);
return client;
}
@@ -387,9 +379,19 @@ public abstract class AbsFtpInfoThread<ENTITY extends AbsEntity, TASK_WRAPPER ex
protected void handleFile(String remotePath, FTPFile ftpFile) {
}
protected void failDownload(BaseException e, boolean needRetry) {
protected void failDownload(FTPClient client, String msg, Exception e, boolean needRetry) {
if (mCallback != null) {
mCallback.onFail(mEntity, e, needRetry);
if (client == null) {
msg = "创建ftp客户端失败";
needRetry = false;
} else {
msg = String.format("%s, code: %s, msg: %s", msg, client.getReplyCode(),
client.getReplyString());
needRetry = needRetry && !CheckUtil.ftpIsBadRequest(client.getReplyCode());
}
//mCallback.onFail(mEntity, new AriaIOException(TAG, msg), needRetry);
mCallback.onFail(mEntity, new AriaIOException(TAG, msg, e), false);
}
}

View File

@@ -22,6 +22,7 @@ import aria.apache.commons.net.ftp.FTPClientConfig;
import aria.apache.commons.net.ftp.FTPReply;
import aria.apache.commons.net.ftp.FTPSClient;
import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.FtpConnectionMode;
import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.task.AbsThreadTaskAdapter;
import com.arialyy.aria.exception.AriaIOException;
@@ -118,7 +119,17 @@ public abstract class BaseFtpThreadTaskAdapter extends AbsThreadTaskAdapter {
client.setControlEncoding(charSet);
client.setDataTimeout(getTaskConfig().getIOTimeOut());
client.setConnectTimeout(getTaskConfig().getConnectTimeOut());
client.enterLocalPassiveMode();
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());
}
} else {
client.enterLocalPassiveMode();
}
client.setFileType(FTP.BINARY_FILE_TYPE);
client.setControlKeepAliveTimeout(5000);
} catch (IOException e) {

View File

@@ -15,6 +15,7 @@
*/
package com.arialyy.aria.ftp;
import aria.apache.commons.net.ftp.FTPClient;
import aria.apache.commons.net.ftp.FTPFile;
import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.CompleteInfo;
@@ -24,8 +25,6 @@ import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.inf.OnFileInfoCallback;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.exception.BaseException;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.RecordUtil;
import java.nio.charset.Charset;
@@ -105,11 +104,11 @@ public class FtpDirInfoThread extends AbsFtpInfoThread<DownloadGroupEntity, DGTa
subOption.setUploadInterceptor(mTaskOption.getUploadInterceptor());
subWrapper.setTaskOption(subOption);
}
@Override protected void failDownload(BaseException e, boolean needRetry) {
super.failDownload(e, needRetry);
@Override
protected void failDownload(FTPClient client, String msg, Exception e, boolean needRetry) {
super.failDownload(client, msg, e, needRetry);
RecordUtil.delGroupTaskRecord(mTaskWrapper.getEntity(), true, true);
}
}

View File

@@ -17,9 +17,10 @@ package com.arialyy.aria.ftp;
import aria.apache.commons.net.ftp.FTPClientConfig;
import com.arialyy.aria.core.FtpUrlEntity;
import com.arialyy.aria.core.common.FtpConnectionMode;
import com.arialyy.aria.core.inf.ITaskOption;
import com.arialyy.aria.core.processor.FtpInterceptHandler;
import com.arialyy.aria.core.processor.IFtpUploadInterceptor;
import com.arialyy.aria.core.inf.ITaskOption;
import java.lang.ref.SoftReference;
import java.net.Proxy;
@@ -55,6 +56,54 @@ public class FtpTaskOption implements ITaskOption {
*/
private FTPClientConfig clientConfig;
/**
* 连接模式,默认为被动模式
* {@link FtpConnectionMode}
*/
private int connMode;
/**
* 主动模式下的端口范围
*/
private int minPort, maxPort;
/**
* 主动模式下对外ip可被Ftp服务器访问的ip
*/
private String activeExternalIPAddress;
public String getActiveExternalIPAddress() {
return activeExternalIPAddress;
}
public void setActiveExternalIPAddress(String activeExternalIPAddress) {
this.activeExternalIPAddress = activeExternalIPAddress;
}
public int getMinPort() {
return minPort;
}
public void setMinPort(int minPort) {
this.minPort = minPort;
}
public int getMaxPort() {
return maxPort;
}
public void setMaxPort(int maxPort) {
this.maxPort = maxPort;
}
public int getConnMode() {
return connMode;
}
public void setConnMode(int connMode) {
this.connMode = connMode;
}
public FTPClientConfig getClientConfig() {
return clientConfig;
}