From 9641d91541a9d5f4cbf398c7239f3ebb3c99af50 Mon Sep 17 00:00:00 2001
From: AriaLyy <511455842@qq.com>
Date: Wed, 26 Jul 2017 17:14:46 +0800
Subject: [PATCH] =?UTF-8?q?ftp=E6=96=87=E4=BB=B6=E5=A4=B9=E4=B8=8B?=
 =?UTF-8?q?=E8=BD=BD=E5=BC=80=E5=A7=8B=E5=AE=9E=E7=8E=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../com/arialyy/aria/core/AriaManager.java    |   3 +-
 .../aria/core/download/BaseGroupTarget.java   | 202 ++++++++++++++++++
 .../core/download/DownloadGroupTarget.java    | 175 +--------------
 .../aria/core/download/DownloadReceiver.java  |  26 ++-
 .../aria/core/download/DownloadTask.java      |   5 -
 .../core/download/DownloadTaskEntity.java     |  11 -
 .../core/download/FtpDirDownloadTarget.java   |  61 ++++++
 .../aria/core/download/FtpDownloadTarget.java |  11 +-
 .../core/download/downloader/Downloader.java  |   5 +-
 .../download/downloader/FtpClientHelp.java    |   3 +-
 .../downloader/SimpleDownloadUtil.java        |   2 +-
 .../arialyy/aria/core/inf/AbsTaskEntity.java  |  11 +
 .../fragment_download/FragmentActivity.java   |   2 +
 .../arialyy/simple/upload/UploadActivity.java |   1 +
 14 files changed, 303 insertions(+), 215 deletions(-)
 create mode 100644 Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java
 create mode 100644 Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java

diff --git a/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java b/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java
index 41bb1525..fa7d2046 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java
@@ -41,6 +41,7 @@ import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.parsers.SAXParser;
 import javax.xml.parsers.SAXParserFactory;
@@ -59,7 +60,7 @@ import org.xml.sax.SAXException;
   public static final String DOWNLOAD_TEMP_DIR = "/Aria/temp/download/";
   public static final String UPLOAD_TEMP_DIR = "/Aria/temp/upload/";
   @SuppressLint("StaticFieldLeak") private static volatile AriaManager INSTANCE = null;
-  private Map<String, IReceiver> mReceivers = new HashMap<>();
+  private Map<String, IReceiver> mReceivers = new ConcurrentHashMap<>();
   public static Context APP;
   private List<ICmd> mCommands = new ArrayList<>();
   private Configuration.DownloadConfig mDConfig;
diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java
new file mode 100644
index 00000000..a1d44a9d
--- /dev/null
+++ b/Aria/src/main/java/com/arialyy/aria/core/download/BaseGroupTarget.java
@@ -0,0 +1,202 @@
+/*
+ * 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;
+
+import android.text.TextUtils;
+import com.arialyy.aria.core.inf.AbsDownloadTarget;
+import com.arialyy.aria.core.inf.AbsTarget;
+import com.arialyy.aria.core.inf.AbsTaskEntity;
+import com.arialyy.aria.orm.DbEntity;
+import com.arialyy.aria.util.CommonUtil;
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by Aria.Lao on 2017/7/26.
+ */
+abstract class BaseGroupTarget<TARGET extends AbsTarget, TASK_ENTITY extends AbsTaskEntity>
+    extends AbsDownloadTarget<TARGET, DownloadGroupEntity, TASK_ENTITY> {
+
+  List<String> mUrls = new ArrayList<>();
+  /**
+   * 子任务文件名
+   */
+  List<String> mSubTaskFileName = new ArrayList<>();
+  String mGroupName;
+  /**
+   * 是否已经设置了文件路径
+   */
+  boolean isSetDirPathed = false;
+
+  /**
+   * 查询任务组实体,如果数据库不存在该实体,则新创建一个新的任务组实体
+   */
+  DownloadGroupEntity getDownloadGroupEntity() {
+    DownloadGroupEntity entity =
+        DbEntity.findFirst(DownloadGroupEntity.class, "groupName=?", mGroupName);
+    if (entity == null) {
+      entity = new DownloadGroupEntity();
+      entity.setGroupName(mGroupName);
+      entity.setUrls(mUrls);
+      entity.insert();
+    }
+    return entity;
+  }
+
+  /**
+   * 设置任务组别名
+   */
+  public TARGET setGroupAlias(String alias) {
+    if (TextUtils.isEmpty(alias)) return (TARGET) this;
+    mEntity.setAlias(alias);
+    mEntity.update();
+    return (TARGET) this;
+  }
+
+  /**
+   * 设置任务组的文件夹路径,在Aria中,任务组的所有子任务都会下载到以任务组组名的文件夹中。
+   * 如:groupDirPath = "/mnt/sdcard/download/group_test"
+   * <pre>
+   *   {@code
+   *      + mnt
+   *        + sdcard
+   *          + download
+   *            + group_test
+   *              - task1.apk
+   *              - task2.apk
+   *              - task3.apk
+   *              ....
+   *
+   *   }
+   * </pre>
+   *
+   * @param groupDirPath 任务组保存文件夹路径
+   */
+  public TARGET setDownloadDirPath(String groupDirPath) {
+    if (TextUtils.isEmpty(groupDirPath)) {
+      throw new NullPointerException("任务组文件夹保存路径不能为null");
+    }
+
+    isSetDirPathed = true;
+    if (mEntity.getDirPath().equals(groupDirPath)) return (TARGET) this;
+
+    File file = new File(groupDirPath);
+    if (file.exists() && file.isFile()) {
+      throw new IllegalArgumentException("路径不能为文件");
+    }
+    if (!file.exists()) {
+      file.mkdirs();
+    }
+
+    mEntity.setDirPath(groupDirPath);
+    if (!TextUtils.isEmpty(mEntity.getDirPath())) {
+      reChangeDirPath(groupDirPath);
+    } else {
+      mEntity.setSubTasks(createSubTask());
+    }
+    mEntity.update();
+    return (TARGET) this;
+  }
+
+  /**
+   * 改变任务组文件夹路径,修改文件夹路径会将子任务所有路径更换
+   *
+   * @param newDirPath 新的文件夹路径
+   */
+  private void reChangeDirPath(String newDirPath) {
+    List<DownloadEntity> subTask = mEntity.getSubTask();
+    if (subTask != null && !subTask.isEmpty()) {
+      for (DownloadEntity entity : subTask) {
+        String oldPath = entity.getDownloadPath();
+        String newPath = newDirPath + "/" + entity.getFileName();
+        File file = new File(oldPath);
+        file.renameTo(new File(newPath));
+        DbEntity.exeSql("UPDATE DownloadEntity SET downloadPath='"
+            + newPath
+            + "' WHERE downloadPath='"
+            + oldPath
+            + "'");
+        DbEntity.exeSql(
+            "UPDATE DownloadTaskEntity SET key='" + newPath + "' WHERE key='" + oldPath + "'");
+      }
+    } else {
+      mEntity.setSubTasks(createSubTask());
+    }
+  }
+
+  /**
+   * 设置子任务文件名,该方法必须在{@link #setDownloadDirPath(String)}之后调用,否则不生效
+   */
+  public TARGET setSubTaskFileName(List<String> subTaskFileName) {
+    if (subTaskFileName == null || subTaskFileName.isEmpty()) return (TARGET) this;
+    mSubTaskFileName.addAll(subTaskFileName);
+    if (mUrls.size() != subTaskFileName.size()) {
+      throw new IllegalArgumentException("下载链接数必须要和保存路径的数量一致");
+    }
+    if (isSetDirPathed) {
+      List<DownloadEntity> entities = mEntity.getSubTask();
+      int i = 0;
+      for (DownloadEntity entity : entities) {
+        String newName = mSubTaskFileName.get(i);
+        updateSubFileName(entity, newName);
+        i++;
+      }
+    }
+    return (TARGET) this;
+  }
+
+  /**
+   * 更新子任务文件名
+   */
+  private void updateSubFileName(DownloadEntity entity, String newName) {
+    if (!newName.equals(entity.getFileName())) {
+      String oldPath = mEntity.getDirPath() + "/" + entity.getFileName();
+      String newPath = mEntity.getDirPath() + "/" + newName;
+      File oldFile = new File(oldPath);
+      if (oldFile.exists()) {
+        oldFile.renameTo(new File(newPath));
+      }
+      CommonUtil.renameDownloadConfig(oldFile.getName(), newName);
+      DbEntity.exeSql(
+          "UPDATE DownloadTaskEntity SET key='" + newPath + "' WHERE key='" + oldPath + "'");
+      entity.setDownloadPath(newPath);
+      entity.setFileName(newName);
+      entity.update();
+    }
+  }
+
+  /**
+   * 创建子任务
+   */
+  private List<DownloadEntity> createSubTask() {
+    List<DownloadEntity> list = new ArrayList<>();
+    for (int i = 0, len = mUrls.size(); i < len; i++) {
+      DownloadEntity entity = new DownloadEntity();
+      entity.setDownloadUrl(mUrls.get(i));
+      String fileName = mSubTaskFileName.isEmpty() ? createFileName(entity.getDownloadUrl())
+          : mSubTaskFileName.get(i);
+      entity.setDownloadPath(mEntity.getDirPath() + "/" + fileName);
+      entity.setGroupName(mGroupName);
+      entity.setGroupChild(true);
+      entity.setFileName(fileName);
+      entity.insert();
+      list.add(entity);
+    }
+    return list;
+  }
+
+}
diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java
index 53f8b79c..33d0529b 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupTarget.java
@@ -15,32 +15,18 @@
  */
 package com.arialyy.aria.core.download;
 
-import android.text.TextUtils;
-import com.arialyy.aria.core.inf.AbsDownloadTarget;
-import com.arialyy.aria.core.inf.AbsUploadTarget;
 import com.arialyy.aria.orm.DbEntity;
 import com.arialyy.aria.util.CheckUtil;
 import com.arialyy.aria.util.CommonUtil;
-import java.io.File;
-import java.util.ArrayList;
 import java.util.List;
 
 /**
  * Created by AriaL on 2017/6/29.
+ * 下载任务组
  */
 public class DownloadGroupTarget
-    extends AbsDownloadTarget<DownloadGroupTarget, DownloadGroupEntity, DownloadGroupTaskEntity> {
-  private List<String> mUrls = new ArrayList<>();
+    extends BaseGroupTarget<DownloadGroupTarget, DownloadGroupTaskEntity> {
   private final String TAG = "DownloadGroupTarget";
-  /**
-   * 子任务文件名
-   */
-  private List<String> mSubTaskFileName = new ArrayList<>();
-  private String mGroupName;
-  /**
-   * 是否已经设置了文件路径
-   */
-  private boolean isSetDirPathed = false;
 
   DownloadGroupTarget(DownloadGroupEntity groupEntity, String targetName) {
     this.mTargetName = targetName;
@@ -71,31 +57,6 @@ public class DownloadGroupTarget
     mEntity = mTaskEntity.entity;
   }
 
-  /**
-   * 查询任务组实体,如果数据库不存在该实体,则新创建一个新的任务组实体
-   */
-  private DownloadGroupEntity getDownloadGroupEntity() {
-    DownloadGroupEntity entity =
-        DbEntity.findFirst(DownloadGroupEntity.class, "groupName=?", mGroupName);
-    if (entity == null) {
-      entity = new DownloadGroupEntity();
-      entity.setGroupName(mGroupName);
-      entity.setUrls(mUrls);
-      entity.insert();
-    }
-    return entity;
-  }
-
-  /**
-   * 设置任务组别名
-   */
-  public DownloadGroupTarget setGroupAlias(String alias) {
-    if (TextUtils.isEmpty(alias)) return this;
-    mEntity.setAlias(alias);
-    mEntity.update();
-    return this;
-  }
-
   /**
    * 如果你是使用{@link DownloadReceiver#load(DownloadGroupEntity)}进行下载操作,那么你需要设置任务组的下载地址
    */
@@ -107,136 +68,4 @@ public class DownloadGroupTarget
     mEntity.update();
     return this;
   }
-
-  /**
-   * 设置任务组的文件夹路径,在Aria中,任务组的所有子任务都会下载到以任务组组名的文件夹中。
-   * 如:groupDirPath = "/mnt/sdcard/download/group_test"
-   * <pre>
-   *   {@code
-   *      + mnt
-   *        + sdcard
-   *          + download
-   *            + group_test
-   *              - task1.apk
-   *              - task2.apk
-   *              - task3.apk
-   *              ....
-   *
-   *   }
-   * </pre>
-   *
-   * @param groupDirPath 任务组保存文件夹路径
-   */
-  public DownloadGroupTarget setDownloadDirPath(String groupDirPath) {
-    if (TextUtils.isEmpty(groupDirPath)) {
-      throw new NullPointerException("任务组文件夹保存路径不能为null");
-    }
-
-    isSetDirPathed = true;
-    if (mEntity.getDirPath().equals(groupDirPath)) return this;
-
-    File file = new File(groupDirPath);
-    if (file.exists() && file.isFile()) {
-      throw new IllegalArgumentException("路径不能为文件");
-    }
-    if (!file.exists()) {
-      file.mkdirs();
-    }
-
-    mEntity.setDirPath(groupDirPath);
-    if (!TextUtils.isEmpty(mEntity.getDirPath())) {
-      reChangeDirPath(groupDirPath);
-    } else {
-      mEntity.setSubTasks(createSubTask());
-    }
-    mEntity.update();
-    return this;
-  }
-
-  /**
-   * 改变任务组文件夹路径,修改文件夹路径会将子任务所有路径更换
-   *
-   * @param newDirPath 新的文件夹路径
-   */
-  private void reChangeDirPath(String newDirPath) {
-    List<DownloadEntity> subTask = mEntity.getSubTask();
-    if (subTask != null && !subTask.isEmpty()) {
-      for (DownloadEntity entity : subTask) {
-        String oldPath = entity.getDownloadPath();
-        String newPath = newDirPath + "/" + entity.getFileName();
-        File file = new File(oldPath);
-        file.renameTo(new File(newPath));
-        DbEntity.exeSql("UPDATE DownloadEntity SET downloadPath='"
-            + newPath
-            + "' WHERE downloadPath='"
-            + oldPath
-            + "'");
-        DbEntity.exeSql(
-            "UPDATE DownloadTaskEntity SET key='" + newPath + "' WHERE key='" + oldPath + "'");
-      }
-    } else {
-      mEntity.setSubTasks(createSubTask());
-    }
-  }
-
-  /**
-   * 设置子任务文件名,该方法必须在{@link #setDownloadDirPath(String)}之后调用,否则不生效
-   */
-  public DownloadGroupTarget setSubTaskFileName(List<String> subTaskFileName) {
-    if (subTaskFileName == null || subTaskFileName.isEmpty()) return this;
-    mSubTaskFileName.addAll(subTaskFileName);
-    if (mUrls.size() != subTaskFileName.size()) {
-      throw new IllegalArgumentException("下载链接数必须要和保存路径的数量一致");
-    }
-    if (isSetDirPathed) {
-      List<DownloadEntity> entities = mEntity.getSubTask();
-      int i = 0;
-      for (DownloadEntity entity : entities) {
-        String newName = mSubTaskFileName.get(i);
-        updateSubFileName(entity, newName);
-        i++;
-      }
-    }
-    return this;
-  }
-
-  /**
-   * 更新子任务文件名
-   */
-  private void updateSubFileName(DownloadEntity entity, String newName) {
-    if (!newName.equals(entity.getFileName())) {
-      String oldPath = mEntity.getDirPath() + "/" + entity.getFileName();
-      String newPath = mEntity.getDirPath() + "/" + newName;
-      File oldFile = new File(oldPath);
-      if (oldFile.exists()) {
-        oldFile.renameTo(new File(newPath));
-      }
-      CommonUtil.renameDownloadConfig(oldFile.getName(), newName);
-      DbEntity.exeSql(
-          "UPDATE DownloadTaskEntity SET key='" + newPath + "' WHERE key='" + oldPath + "'");
-      entity.setDownloadPath(newPath);
-      entity.setFileName(newName);
-      entity.update();
-    }
-  }
-
-  /**
-   * 创建子任务
-   */
-  private List<DownloadEntity> createSubTask() {
-    List<DownloadEntity> list = new ArrayList<>();
-    for (int i = 0, len = mUrls.size(); i < len; i++) {
-      DownloadEntity entity = new DownloadEntity();
-      entity.setDownloadUrl(mUrls.get(i));
-      String fileName = mSubTaskFileName.isEmpty() ? createFileName(entity.getDownloadUrl())
-          : mSubTaskFileName.get(i);
-      entity.setDownloadPath(mEntity.getDirPath() + "/" + fileName);
-      entity.setGroupName(mGroupName);
-      entity.setGroupChild(true);
-      entity.setFileName(fileName);
-      entity.insert();
-      list.add(entity);
-    }
-    return list;
-  }
 }
diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java
index 270b1059..f6fc837a 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java
@@ -58,21 +58,13 @@ public class DownloadReceiver extends AbsReceiver {
   }
 
   /**
-   * 加载Http、https
+   * 加载Http、https单任务下载地址
    */
   public DownloadTarget load(@NonNull String url) {
     CheckUtil.checkDownloadUrl(url);
     return new DownloadTarget(url, targetName);
   }
 
-  /**
-   * 加载ftp下载地址
-   */
-  public FtpDownloadTarget loadFtp(@NonNull String url) {
-    CheckUtil.checkDownloadUrl(url);
-    return new FtpDownloadTarget(url, targetName);
-  }
-
   /**
    * 加载下载地址,如果任务组的中的下载地址改变了,则任务从新的一个任务组
    */
@@ -81,6 +73,14 @@ public class DownloadReceiver extends AbsReceiver {
     return new DownloadGroupTarget(urls, targetName);
   }
 
+  /**
+   * 加载ftp单任务下载地址
+   */
+  public FtpDownloadTarget loadFtp(@NonNull String url) {
+    CheckUtil.checkDownloadUrl(url);
+    return new FtpDownloadTarget(url, targetName);
+  }
+
   /**
    * 使用任务组实体执行任务组的实体执行任务组的下载操作
    *
@@ -91,6 +91,14 @@ public class DownloadReceiver extends AbsReceiver {
     return new DownloadGroupTarget(groupEntity, targetName);
   }
 
+  /**
+   * 加载ftp文件夹下载地址
+   */
+  public FtpDirDownloadTarget loadFtpDir(@NonNull String dirUrl) {
+    CheckUtil.checkDownloadUrl(dirUrl);
+    return new FtpDirDownloadTarget(dirUrl, targetName);
+  }
+
   /**
    * 将当前类注册到Aria
    */
diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java
index e43b0eeb..e82864a0 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTask.java
@@ -42,11 +42,6 @@ public class DownloadTask extends AbsNormalTask<DownloadEntity> {
     mContext = AriaManager.APP;
     mListener = new DownloadListener(this, mOutHandler);
     mUtil = new SimpleDownloadUtil(taskEntity, mListener);
-    //if (taskEntity.downloadType == AbsTaskEntity.HTTP) {
-    //  mUtil = new SimpleDownloadUtil(taskEntity, mListener);
-    //}else if (taskEntity.downloadType == AbsTaskEntity.FTP){
-    //  mUtil = new FtpDownloadUtil(taskEntity, mListener);
-    //}
   }
 
   /**
diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java
index bcf5ba5c..a3ec37a6 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadTaskEntity.java
@@ -30,17 +30,6 @@ public class DownloadTaskEntity extends AbsTaskEntity<DownloadEntity> {
    */
   @Ignore public String userName, userPw, account;
 
-  /**
-   * FTP服务器文件或文件夹路径
-   */
-  public String remotePath;
-
-  /**
-   * 下载类型
-   * {@link AbsTaskEntity#HTTP}、{@link AbsTaskEntity#FTP}
-   */
-  public int downloadType = HTTP;
-
   @OneToOne(table = DownloadEntity.class, key = "downloadPath") public DownloadEntity entity;
 
   /**
diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java
new file mode 100644
index 00000000..44af63e0
--- /dev/null
+++ b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java
@@ -0,0 +1,61 @@
+/*
+ * 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;
+
+import android.text.TextUtils;
+import com.arialyy.aria.core.inf.AbsTaskEntity;
+import com.arialyy.aria.orm.DbEntity;
+
+/**
+ * Created by Aria.Lao on 2017/7/26.
+ * ftp文件夹下载
+ */
+public class FtpDirDownloadTarget
+    extends BaseGroupTarget<FtpDownloadTarget, DownloadGroupTaskEntity> {
+  private String serverIp, remotePath, mGroupName;
+  private int port;
+
+  FtpDirDownloadTarget(String url, String targetName) {
+    init(url);
+    String[] pp = url.split("/")[2].split(":");
+    this.serverIp = pp[0];
+    this.port = Integer.parseInt(pp[1]);
+    mTaskEntity.requestType = AbsTaskEntity.FTP;
+    remotePath = url.substring(url.indexOf(pp[1]) + pp[1].length(), url.length());
+    if (TextUtils.isEmpty(remotePath)) {
+      throw new NullPointerException("ftp服务器地址不能为null");
+    }
+    mTargetName = targetName;
+    int lastIndex = url.lastIndexOf("/");
+    mTaskEntity.remotePath = remotePath;
+    mEntity.setDirPath(url.substring(lastIndex + 1, url.length()));
+  }
+
+  private void init(String key) {
+    mGroupName = key;
+    mTaskEntity = DbEntity.findFirst(DownloadGroupTaskEntity.class, "key=?", key);
+    if (mTaskEntity == null) {
+      mTaskEntity = new DownloadGroupTaskEntity();
+      mTaskEntity.key = key;
+      mTaskEntity.entity = getDownloadGroupEntity();
+      mTaskEntity.insert();
+    }
+    if (mTaskEntity.entity == null) {
+      mTaskEntity.entity = getDownloadGroupEntity();
+    }
+    mEntity = mTaskEntity.entity;
+  }
+}
diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java
index af4d6097..a750ee3c 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java
@@ -36,13 +36,12 @@ public class FtpDownloadTarget extends DownloadTarget {
     String[] pp = url.split("/")[2].split(":");
     this.serverIp = pp[0];
     this.port = Integer.parseInt(pp[1]);
-    mTaskEntity.downloadType = AbsTaskEntity.FTP;
+    mTaskEntity.requestType = AbsTaskEntity.FTP;
     remotePath = url.substring(url.indexOf(pp[1]) + pp[1].length(), url.length());
     if (TextUtils.isEmpty(remotePath)) {
       throw new NullPointerException("ftp服务器地址不能为null");
     }
     int lastIndex = url.lastIndexOf("/");
-    mTaskEntity.downloadType = AbsTaskEntity.FTP;
     mTaskEntity.remotePath = remotePath;
     mEntity.setFileName(url.substring(lastIndex + 1, url.length()));
   }
@@ -115,14 +114,6 @@ public class FtpDownloadTarget extends DownloadTarget {
     mTaskEntity.userName = userName;
     mTaskEntity.userPw = password;
     mTaskEntity.account = account;
-    //FtpClientHelp.getInstnce().login(serverIp, port, userName, password, account);
     return this;
   }
-
-  ///**
-  // * 当所有任务都完成时,需要登出ftp服务器
-  // */
-  //public void logout() {
-  //  FtpClientHelp.getInstnce().logout();
-  //}
 }
diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java
index ed504a61..89df24d3 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/Downloader.java
@@ -16,7 +16,6 @@
 package com.arialyy.aria.core.download.downloader;
 
 import android.content.Context;
-import android.text.TextUtils;
 import android.util.Log;
 import android.util.SparseArray;
 import com.arialyy.aria.core.AriaManager;
@@ -34,8 +33,6 @@ import java.util.Timer;
 import java.util.TimerTask;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
-import org.apache.commons.net.ftp.FTPClient;
-import org.apache.commons.net.ftp.FTPReply;
 
 /**
  * Created by AriaL on 2017/7/1.
@@ -417,7 +414,7 @@ class Downloader implements Runnable, IDownloadUtil {
   }
 
   private AbsThreadTask createThreadTask(SubThreadConfig config) {
-    switch (mTaskEntity.downloadType) {
+    switch (mTaskEntity.requestType) {
       case AbsTaskEntity.FTP:
         config.remotePath = mTaskEntity.remotePath;
         return new FtpThreadTask(mConstance, mListener, config);
diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpClientHelp.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpClientHelp.java
index a9172836..338d114b 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpClientHelp.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpClientHelp.java
@@ -55,7 +55,7 @@ public class FtpClientHelp {
   /**
    * 登录到FTP服务器,当客户端为null或客户端没有连接到FTP服务器时才会执行登录操作
    */
-  public void login(String serverIp, int port, String user, String pw, String account) {
+  public FTPClient login(String serverIp, int port, String user, String pw, String account) {
     this.serverIp = serverIp;
     this.port = port;
     this.user = user;
@@ -64,6 +64,7 @@ public class FtpClientHelp {
     if (client == null || !client.isConnected()) {
       createClient();
     }
+    return client;
   }
 
   /**
diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/SimpleDownloadUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/SimpleDownloadUtil.java
index 15966955..cfe0b559 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/SimpleDownloadUtil.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/SimpleDownloadUtil.java
@@ -98,7 +98,7 @@ public class SimpleDownloadUtil implements IDownloadUtil, Runnable {
    * 通过链接类型创建不同的获取文件信息的线程
    */
   private Runnable createInfoThread() {
-    switch (mTaskEntity.downloadType) {
+    switch (mTaskEntity.requestType) {
       case AbsTaskEntity.FTP:
         return new FtpFileInfoThread(mTaskEntity, new OnFileInfoCallback() {
           @Override public void onComplete(String url, int code) {
diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTaskEntity.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTaskEntity.java
index d28de70d..8458150b 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTaskEntity.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTaskEntity.java
@@ -34,6 +34,17 @@ public abstract class AbsTaskEntity<ENTITY extends AbsEntity> extends DbEntity {
    */
   @Primary public String key = "";
 
+  /**
+   * FTP服务器文件或文件夹路径
+   */
+  public String remotePath;
+
+  /**
+   * 请求类型
+   * {@link AbsTaskEntity#HTTP}、{@link AbsTaskEntity#FTP}
+   */
+  public int requestType = HTTP;
+
   /**
    * http 请求头
    */
diff --git a/app/src/main/java/com/arialyy/simple/download/fragment_download/FragmentActivity.java b/app/src/main/java/com/arialyy/simple/download/fragment_download/FragmentActivity.java
index 93ab023f..adb2fc96 100644
--- a/app/src/main/java/com/arialyy/simple/download/fragment_download/FragmentActivity.java
+++ b/app/src/main/java/com/arialyy/simple/download/fragment_download/FragmentActivity.java
@@ -17,6 +17,7 @@
 package com.arialyy.simple.download.fragment_download;
 
 import android.os.Bundle;
+import com.arialyy.aria.core.Aria;
 import com.arialyy.simple.R;
 import com.arialyy.simple.base.BaseActivity;
 import com.arialyy.simple.databinding.FragmentDownloadBinding;
@@ -33,5 +34,6 @@ public class FragmentActivity extends BaseActivity<FragmentDownloadBinding> {
   @Override protected void init(Bundle savedInstanceState) {
     super.init(savedInstanceState);
     setTile("Fragment 中使用");
+    Aria.download(this).register();
   }
 }
diff --git a/app/src/main/java/com/arialyy/simple/upload/UploadActivity.java b/app/src/main/java/com/arialyy/simple/upload/UploadActivity.java
index 70373fbe..d3d0c42a 100644
--- a/app/src/main/java/com/arialyy/simple/upload/UploadActivity.java
+++ b/app/src/main/java/com/arialyy/simple/upload/UploadActivity.java
@@ -79,6 +79,7 @@ public class UploadActivity extends BaseActivity<ActivityUploadMeanBinding> {
 
   @Override protected void init(Bundle savedInstanceState) {
     super.init(savedInstanceState);
+    setTile("http上传");
     Aria.upload(this).register();
   }