diff --git a/.gitignore b/.gitignore
index 2f961d9e..6b0f8a6a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,4 +12,5 @@
 .gradle
 /.idea
 .idea
-/cache
\ No newline at end of file
+/cache
+*.log
\ No newline at end of file
diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java b/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java
index a387a4d9..a9af7000 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/common/AbsFileer.java
@@ -99,18 +99,17 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
       mConstance.THREAD_NUM = mThreadNum;
       handleNoSupportBP();
     } else {
-      mThreadNum = isNewTask ? (getThreadNum()) : mRealThreadNum;
+      mThreadNum = isNewTask ? (getNewTaskThreadNum()) : mRealThreadNum;
       mConstance.THREAD_NUM = mThreadNum;
-      mFixedThreadPool = Executors.newFixedThreadPool(mThreadNum);
       handleBreakpoint();
     }
     startTimer();
   }
 
   /**
-   * 获取线程数
+   * 设置新任务的最大线程数
    */
-  protected int getThreadNum() {
+  protected int getNewTaskThreadNum() {
     return mEntity.getFileSize() <= SUB_LEN || mTaskEntity.requestType == AbsTaskEntity.FTP_DIR ? 1
         : AriaManager.getInstance(mContext).getDownloadConfig().getThreadNum();
   }
@@ -292,25 +291,6 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
     return selectThreadTask(config);
   }
 
-  /**
-   * 启动单线程下载任务
-   */
-  private void startSingleTask(int[] recordL) {
-    if (mConstance.CURRENT_LOCATION > 0) {
-      mListener.onResume(mConstance.CURRENT_LOCATION);
-    } else {
-      mListener.onStart(mConstance.CURRENT_LOCATION);
-    }
-    mFixedThreadPool = Executors.newFixedThreadPool(recordL.length);
-    for (int l : recordL) {
-      if (l == -1) continue;
-      Runnable task = mTask.get(l);
-      if (task != null) {
-        mFixedThreadPool.execute(task);
-      }
-    }
-  }
-
   /**
    * 处理断点
    */
@@ -358,6 +338,28 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
     startSingleTask(recordL);
   }
 
+  /**
+   * 启动单线程下载任务
+   */
+  private void startSingleTask(int[] recordL) {
+    if (mConstance.CURRENT_LOCATION > 0) {
+      mListener.onResume(mConstance.CURRENT_LOCATION);
+    } else {
+      mListener.onStart(mConstance.CURRENT_LOCATION);
+    }
+    mFixedThreadPool = Executors.newFixedThreadPool(recordL.length);
+    for (int l : recordL) {
+      if (l == -1) continue;
+      Runnable task = mTask.get(l);
+      if (task != null) {
+        mFixedThreadPool.execute(task);
+      }
+    }
+  }
+
+  /**
+   * 处理新任务
+   */
   protected abstract void handleNewTask();
 
   /**
@@ -377,6 +379,7 @@ public abstract class AbsFileer<ENTITY extends AbsNormalEntity, TASK_ENTITY exte
     AbsThreadTask task = selectThreadTask(config);
     if (task == null) return;
     mTask.put(0, task);
+    mFixedThreadPool = Executors.newFixedThreadPool(1);
     mFixedThreadPool.execute(task);
     mListener.onStart(0);
   }
diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/AbsThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/common/AbsThreadTask.java
index 3f525881..316d6cbc 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/common/AbsThreadTask.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/common/AbsThreadTask.java
@@ -22,6 +22,7 @@ import com.arialyy.aria.core.AriaManager;
 import com.arialyy.aria.core.inf.AbsEntity;
 import com.arialyy.aria.core.inf.AbsTaskEntity;
 import com.arialyy.aria.core.inf.IEventListener;
+import com.arialyy.aria.core.upload.UploadEntity;
 import com.arialyy.aria.util.CommonUtil;
 import java.io.File;
 import java.io.IOException;
@@ -134,7 +135,7 @@ public abstract class AbsThreadTask<ENTITY extends AbsEntity, TASK_ENTITY extend
           if (configFile.exists()) {
             configFile.delete();
           }
-          if (mConfig.TEMP_FILE.exists()) {
+          if (mConfig.TEMP_FILE.exists() && !(mEntity instanceof UploadEntity)) {
             mConfig.TEMP_FILE.delete();
           }
           Log.d(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】已取消");
diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/BaseListener.java b/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java
similarity index 97%
rename from Aria/src/main/java/com/arialyy/aria/core/download/BaseListener.java
rename to Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java
index de30a6e5..0b02c968 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/download/BaseListener.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java
@@ -30,7 +30,7 @@ import java.lang.ref.WeakReference;
 /**
  * 下载监听类
  */
-class BaseListener<ENTITY extends AbsEntity, TASK extends AbsTask<ENTITY>>
+class BaseDListener<ENTITY extends AbsEntity, TASK extends AbsTask<ENTITY>>
     implements IDownloadListener {
   private WeakReference<Handler> outHandler;
   private long mLastLen = 0;   //上一次发送长度
@@ -40,7 +40,7 @@ class BaseListener<ENTITY extends AbsEntity, TASK extends AbsTask<ENTITY>>
   private boolean isConvertSpeed = false;
   boolean isWait = false;
 
-  BaseListener(TASK task, Handler outHandler) {
+  BaseDListener(TASK task, Handler outHandler) {
     this.outHandler = new WeakReference<>(outHandler);
     this.mTask = new WeakReference<>(task).get();
     this.mEntity = this.mTask.getEntity();
diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupListener.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupListener.java
index e590bd1a..650772b6 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupListener.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupListener.java
@@ -16,14 +16,13 @@
 package com.arialyy.aria.core.download;
 
 import android.os.Handler;
-import android.util.Log;
 import com.arialyy.aria.core.download.downloader.IDownloadGroupListener;
 
 /**
  * Created by Aria.Lao on 2017/7/20.
  * 任务组下载事件
  */
-class DownloadGroupListener extends BaseListener<DownloadGroupEntity, DownloadGroupTask>
+class DownloadGroupListener extends BaseDListener<DownloadGroupEntity, DownloadGroupTask>
     implements IDownloadGroupListener {
   private final String TAG = "DownloadGroupListener";
 
diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadListener.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadListener.java
index 7afc6b57..319c3a58 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadListener.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadListener.java
@@ -22,7 +22,7 @@ import com.arialyy.aria.core.inf.IDownloadListener;
  * Created by Aria.Lao on 2017/7/20.
  * 普通任务下载的事件监听器
  */
-class DownloadListener extends BaseListener<DownloadEntity, DownloadTask>
+class DownloadListener extends BaseDListener<DownloadEntity, DownloadTask>
     implements IDownloadListener {
   DownloadListener(DownloadTask task, Handler outHandler) {
     super(task, outHandler);
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 1954f9c9..78738926 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
@@ -139,14 +139,12 @@ public class DownloadTask extends AbsNormalTask<DownloadEntity> {
    * 取消下载
    */
   @Override public void cancel() {
-    if (!mEntity.isComplete()) {
-      if (!mUtil.isRunning()) {
-        if (mOutHandler != null) {
-          mOutHandler.obtainMessage(ISchedulers.CANCEL, this).sendToTarget();
-        }
+    if (!mUtil.isRunning()) {
+      if (mOutHandler != null) {
+        mOutHandler.obtainMessage(ISchedulers.CANCEL, this).sendToTarget();
       }
-      mUtil.cancel();
     }
+    mUtil.cancel();
   }
 
   public static class Builder {
diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java
index a2387ae7..275000eb 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java
@@ -37,7 +37,6 @@ class HttpFileInfoThread implements Runnable {
   private int mConnectTimeOut;
   private OnFileInfoCallback onFileInfoListener;
 
-
   HttpFileInfoThread(DownloadTaskEntity taskEntity, OnFileInfoCallback callback) {
     this.mTaskEntity = taskEntity;
     mEntity = taskEntity.getEntity();
@@ -73,7 +72,8 @@ class HttpFileInfoThread implements Runnable {
   private void handleConnect(HttpURLConnection conn) throws IOException {
     long len = conn.getContentLength();
     if (len < 0) {
-      len = Long.parseLong(conn.getHeaderField(mTaskEntity.contentLength));
+      String temp = conn.getHeaderField(mTaskEntity.contentLength);
+      len = TextUtils.isEmpty(temp) ? -1 : Long.parseLong(temp);
     }
     int code = conn.getResponseCode();
     boolean isComplete = false;
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 59776071..62236c33 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
@@ -16,7 +16,6 @@
 
 package com.arialyy.aria.core.download.downloader;
 
-import android.util.Log;
 import com.arialyy.aria.core.common.IUtil;
 import com.arialyy.aria.core.download.DownloadTaskEntity;
 import com.arialyy.aria.core.inf.AbsTaskEntity;
@@ -71,7 +70,6 @@ public class SimpleDownloadUtil implements IUtil, Runnable {
    * 多线程断点续传下载文件,开始下载
    */
   @Override public void start() {
-    mListener.onPre();
     new Thread(this).start();
   }
 
@@ -84,11 +82,11 @@ public class SimpleDownloadUtil implements IUtil, Runnable {
   }
 
   private void failDownload(String msg) {
-    Log.e(TAG, msg);
     mListener.onFail();
   }
 
   @Override public void run() {
+    mListener.onPre();
     if (mTaskEntity.getEntity().getFileSize() <= 1) {
       new Thread(createInfoThread()).start();
     } else {
diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java
index c60d8be5..3d34306e 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsTarget.java
@@ -153,7 +153,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
   }
 
   /**
-   * 开始下载
+   * 开始任务
    */
   @Override public void start() {
     AriaManager.getInstance(AriaManager.APP)
@@ -162,7 +162,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
   }
 
   /**
-   * 停止下载
+   * 停止任务
    *
    * @see #stop()
    */
@@ -177,7 +177,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
   }
 
   /**
-   * 恢复下载
+   * 恢复任务
    */
   @Override public void resume() {
     AriaManager.getInstance(AriaManager.APP)
@@ -186,7 +186,7 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
   }
 
   /**
-   * 取消下载
+   * 删除任务
    */
   @Override public void cancel() {
     AriaManager.getInstance(AriaManager.APP)
@@ -194,6 +194,19 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
         .exe();
   }
 
+  /**
+   * 删除任务
+   *
+   * @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经删除完成的文件
+   * {@code false}如果任务已经完成,只删除任务数据库记录,
+   */
+  public void cancel(boolean removeFile) {
+    mTaskEntity.removeFile = removeFile;
+    AriaManager.getInstance(AriaManager.APP)
+        .setCmd(CommonUtil.createCmd(mTargetName, mTaskEntity, NormalCmdFactory.TASK_CANCEL))
+        .exe();
+  }
+
   /**
    * 创建文件名,如果url链接有后缀名,则使用url中的后缀名
    *
diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java
index dc347eee..0242daf3 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java
@@ -24,37 +24,37 @@ public interface IReceiver<ENTITY extends IEntity> {
   /**
    * Receiver 销毁
    */
-  public void destroy();
+  void destroy();
 
   /**
    * 移除事件回调
    */
-  public void removeSchedulerListener();
+  void removeSchedulerListener();
 
   /**
    * 移除观察者
    */
-  public void unRegister();
+  void unRegister();
 
   /**
    * 停止所有任务
    */
-  public void stopAllTask();
+  void stopAllTask();
 
   /**
    * 删除所有任务
    */
-  public void removeAllTask(boolean removeFile);
+  void removeAllTask(boolean removeFile);
 
   /**
    * 任务是否存在
    *
    * @param key 下载时为下载路径,上传时为文件路径
    */
-  public boolean taskExists(String key);
+  boolean taskExists(String key);
 
   /**
    * 获取任务列表
    */
-  public List<ENTITY> getSimpleTaskList();
+  List<ENTITY> getSimpleTaskList();
 }
diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/IUploadListener.java b/Aria/src/main/java/com/arialyy/aria/core/inf/IUploadListener.java
index 944a148c..3387c49d 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/inf/IUploadListener.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/inf/IUploadListener.java
@@ -23,8 +23,4 @@ import com.arialyy.aria.core.inf.IEventListener;
  */
 public interface IUploadListener extends IEventListener {
 
-  /**
-   * 上传完成,服务器返回的状态码
-   */
-  void onComplete(int state);
 }
diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java
index 2be98fe3..b8128680 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java
@@ -25,45 +25,45 @@ public interface ISchedulerListener<TASK extends ITask> {
    * 预处理,有时有些地址链接比较慢,这时可以先在这个地方出来一些界面上的UI,如按钮的状态。
    * 在这个回调中,任务是获取不到文件大小,下载速度等参数
    */
-  public void onPre(TASK task);
+  void onPre(TASK task);
 
   /**
    * 任务预加载完成
    */
-  public void onTaskPre(TASK task);
+  void onTaskPre(TASK task);
 
   /**
    * 任务恢复下载
    */
-  public void onTaskResume(TASK task);
+  void onTaskResume(TASK task);
 
   /**
    * 任务开始
    */
-  public void onTaskStart(TASK task);
+  void onTaskStart(TASK task);
 
   /**
    * 任务停止
    */
-  public void onTaskStop(TASK task);
+  void onTaskStop(TASK task);
 
   /**
    * 任务取消
    */
-  public void onTaskCancel(TASK task);
+  void onTaskCancel(TASK task);
 
   /**
    * 任务下载失败
    */
-  public void onTaskFail(TASK task);
+  void onTaskFail(TASK task);
 
   /**
    * 任务完成
    */
-  public void onTaskComplete(TASK task);
+  void onTaskComplete(TASK task);
 
   /**
    * 任务执行中
    */
-  public void onTaskRunning(TASK task);
+  void onTaskRunning(TASK task);
 }
\ No newline at end of file
diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java b/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java
new file mode 100644
index 00000000..299726e4
--- /dev/null
+++ b/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java
@@ -0,0 +1,138 @@
+/*
+ * 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.upload;
+
+import android.os.Handler;
+import com.arialyy.aria.core.AriaManager;
+import com.arialyy.aria.core.inf.AbsEntity;
+import com.arialyy.aria.core.inf.AbsTask;
+import com.arialyy.aria.core.inf.IEntity;
+import com.arialyy.aria.core.inf.IUploadListener;
+import com.arialyy.aria.core.scheduler.ISchedulers;
+import com.arialyy.aria.util.CommonUtil;
+import java.lang.ref.WeakReference;
+
+/**
+ * 下载监听类
+ */
+class BaseUListener<ENTITY extends AbsEntity, TASK extends AbsTask<ENTITY>>
+    implements IUploadListener {
+  private WeakReference<Handler> outHandler;
+  private long mLastLen = 0;   //上一次发送长度
+  private boolean isFirst = true;
+  protected ENTITY mEntity;
+  protected TASK mTask;
+  private boolean isConvertSpeed = false;
+  boolean isWait = false;
+
+  BaseUListener(TASK task, Handler outHandler) {
+    this.outHandler = new WeakReference<>(outHandler);
+    this.mTask = new WeakReference<>(task).get();
+    this.mEntity = this.mTask.getEntity();
+    final AriaManager manager = AriaManager.getInstance(AriaManager.APP);
+    isConvertSpeed = manager.getDownloadConfig().isConvertSpeed();
+    mLastLen = mEntity.getCurrentProgress();
+  }
+
+  @Override public void onPre() {
+    saveData(IEntity.STATE_PRE, -1);
+    sendInState2Target(ISchedulers.PRE);
+  }
+
+  @Override public void onStart(long startLocation) {
+    saveData(IEntity.STATE_RUNNING, startLocation);
+    sendInState2Target(ISchedulers.START);
+  }
+
+  @Override public void onResume(long resumeLocation) {
+    saveData(IEntity.STATE_RUNNING, resumeLocation);
+    sendInState2Target(ISchedulers.RESUME);
+  }
+
+  @Override public void onProgress(long currentLocation) {
+    mEntity.setCurrentProgress(currentLocation);
+    long speed = currentLocation - mLastLen;
+    if (isFirst) {
+      speed = 0;
+      isFirst = false;
+    }
+    handleSpeed(speed);
+    sendInState2Target(ISchedulers.RUNNING);
+    mLastLen = currentLocation;
+  }
+
+  @Override public void onStop(long stopLocation) {
+    saveData(isWait ? IEntity.STATE_WAIT : IEntity.STATE_STOP, stopLocation);
+    handleSpeed(0);
+    sendInState2Target(ISchedulers.STOP);
+  }
+
+  @Override public void onCancel() {
+    saveData(IEntity.STATE_CANCEL, -1);
+    handleSpeed(0);
+    sendInState2Target(ISchedulers.CANCEL);
+  }
+
+  @Override public void onComplete() {
+    saveData(IEntity.STATE_COMPLETE, mEntity.getFileSize());
+    handleSpeed(0);
+    sendInState2Target(ISchedulers.COMPLETE);
+  }
+
+  @Override public void onFail() {
+    mEntity.setFailNum(mEntity.getFailNum() + 1);
+    saveData(IEntity.STATE_FAIL, mEntity.getCurrentProgress());
+    handleSpeed(0);
+    sendInState2Target(ISchedulers.FAIL);
+  }
+
+  private void handleSpeed(long speed) {
+    if (isConvertSpeed) {
+      mEntity.setConvertSpeed(CommonUtil.formatFileSize(speed < 0 ? 0 : speed) + "/s");
+    } else {
+      mEntity.setSpeed(speed < 0 ? 0 : speed);
+    }
+  }
+
+  /**
+   * 将任务状态发送给下载器
+   *
+   * @param state {@link ISchedulers#START}
+   */
+  private void sendInState2Target(int state) {
+    if (outHandler.get() != null) {
+      outHandler.get().obtainMessage(state, mTask).sendToTarget();
+    }
+  }
+
+  private void saveData(int state, long location) {
+    mEntity.setComplete(state == IEntity.STATE_COMPLETE);
+    if (state == IEntity.STATE_CANCEL) {
+      mEntity.deleteData();
+    } else if (state == IEntity.STATE_COMPLETE) {
+      mEntity.setState(state);
+      mEntity.setCompleteTime(System.currentTimeMillis());
+      mEntity.setCurrentProgress(mEntity.getFileSize());
+      mEntity.update();
+    } else {
+      mEntity.setState(state);
+      if (location != -1) {
+        mEntity.setCurrentProgress(location);
+      }
+      mEntity.update();
+    }
+  }
+}
\ No newline at end of file
diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadListener.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadListener.java
index 3ef60eb3..bf43c7bd 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadListener.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadListener.java
@@ -52,8 +52,4 @@ class UploadListener implements IUploadListener {
   @Override public void onFail() {
 
   }
-
-  @Override public void onComplete(int state) {
-
-  }
 }
diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java
index 8c7dfa16..8b4f4f6b 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java
@@ -35,7 +35,7 @@ import java.util.Set;
  * 上传功能接收器
  */
 public class UploadReceiver extends AbsReceiver<UploadEntity> {
-  private static final String TAG = "DownloadReceiver";
+  private static final String TAG = "UploadReceiver";
   public ISchedulerListener<UploadTask> listener;
 
   /**
@@ -62,7 +62,6 @@ public class UploadReceiver extends AbsReceiver<UploadEntity> {
    * 通过上传路径获取上传实体
    */
   public UploadEntity getUploadEntity(String filePath) {
-    CheckUtil.checkUploadPath(filePath);
     return DbEntity.findFirst(UploadEntity.class, "filePath=?", filePath);
   }
 
diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java
index 154226a4..094f3c36 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java
@@ -39,6 +39,7 @@ public class UploadTarget extends AbsUploadTarget<UploadTarget, UploadEntity, Up
     if (mTaskEntity.entity == null) {
       mTaskEntity.entity = getUploadEntity(filePath);
     }
+    mEntity = mTaskEntity.entity;
     File file = new File(filePath);
     mEntity.setFileSize(file.length());
     mEntity = mTaskEntity.entity;
diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java
index c02fb5de..708f1fd5 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/FtpThreadTask.java
@@ -35,11 +35,11 @@ import org.apache.commons.net.ftp.FTPReply;
 
 /**
  * Created by Aria.Lao on 2017/7/28.
- * FTP 单线程下载器
+ * FTP 单线程上传任务,需要FTP 服务器给用户打开删除和读入IO的权限
  */
 class FtpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
   private final String TAG = "FtpThreadTask";
-  private String remotePath, charSet;
+  private String dir, remotePath, charSet;
 
   FtpThreadTask(StateConstance constance, IEventListener listener,
       SubThreadConfig<UploadTaskEntity> info) {
@@ -64,8 +64,8 @@ class FtpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
       mChildCurrentLocation = mConfig.START_LOCATION;
       client = createClient();
       if (client == null) return;
-      client.makeDirectory(remotePath);
-      client.changeWorkingDirectory(remotePath);
+      client.makeDirectory(dir);
+      client.changeWorkingDirectory(dir);
       client.setRestartOffset(mConfig.START_LOCATION);
       file = new BufferedRandomAccessFile(mConfig.TEMP_FILE, "rwd", mBufSize);
       file.seek(mConfig.START_LOCATION);
@@ -154,9 +154,8 @@ class FtpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
     String[] pp = url.split("/")[2].split(":");
     String serverIp = pp[0];
     int port = Integer.parseInt(pp[1]);
-    remotePath = url.substring(url.indexOf(pp[1]) + pp[1].length(), url.length())
-        + "/"
-        + mEntity.getFileName();
+    dir = url.substring(url.indexOf(pp[1]) + pp[1].length(), url.length());
+    remotePath = dir + "/" + mEntity.getFileName();
     FTPClient client = new FTPClient();
     client.connect(serverIp, port);
     if (!TextUtils.isEmpty(mTaskEntity.account)) {
diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/HttpThreadTask.java b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/HttpThreadTask.java
index 7a90b1da..c6f2db22 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/HttpThreadTask.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/HttpThreadTask.java
@@ -49,7 +49,7 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
   private long mCurrentLocation = 0;
   private OutputStream mOutputStream;
 
-  public HttpThreadTask(StateConstance constance, IUploadListener listener,
+  HttpThreadTask(StateConstance constance, IUploadListener listener,
       SubThreadConfig<UploadTaskEntity> uploadInfo) {
     super(constance, listener, uploadInfo);
   }
@@ -89,7 +89,6 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
       for (String key : keys) {
         addFormField(writer, key, mTaskEntity.formFields.get(key));
       }
-      mListener.onStart(0);
       uploadFile(writer, mTaskEntity.attachment, uploadFile);
       Log.d(TAG, finish(writer) + "");
     } catch (IOException e) {
@@ -101,6 +100,7 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
   private void fail() {
     try {
       mListener.onFail();
+      STATE.isRunning = false;
       if (mOutputStream != null) {
         mOutputStream.close();
       }
@@ -167,9 +167,11 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
     writer.flush();
     if (STATE.isCancel) {
       mListener.onCancel();
+      STATE.isRunning = false;
       return;
     }
     mListener.onComplete();
+    STATE.isRunning = false;
   }
 
   /**
@@ -195,7 +197,7 @@ class HttpThreadTask extends AbsThreadTask<UploadEntity, UploadTaskEntity> {
       mHttpConn.disconnect();
     } else {
       Log.w(TAG, "state_code = " + status);
-      mListener.onFail();
+      fail();
     }
 
     writer.flush();
diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/SimpleHttpUploadUtil.java b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/SimpleUploadUtil.java
similarity index 87%
rename from Aria/src/main/java/com/arialyy/aria/core/upload/uploader/SimpleHttpUploadUtil.java
rename to Aria/src/main/java/com/arialyy/aria/core/upload/uploader/SimpleUploadUtil.java
index 00163397..634f616c 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/SimpleHttpUploadUtil.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/SimpleUploadUtil.java
@@ -23,17 +23,17 @@ import com.arialyy.aria.util.CheckUtil;
 
 /**
  * Created by lyy on 2017/2/9.
- * 简单的http文件上传工具
+ * 简单的文件上传工具
  */
-public class SimpleHttpUploadUtil implements IUtil, Runnable {
-  private static final String TAG = "SimpleHttpUploadUtil";
+public class SimpleUploadUtil implements IUtil, Runnable {
+  private static final String TAG = "SimpleUploadUtil";
 
   private UploadEntity mUploadEntity;
   private UploadTaskEntity mTaskEntity;
   private IUploadListener mListener;
   private Uploader mUploader;
 
-  public SimpleHttpUploadUtil(UploadTaskEntity taskEntity, IUploadListener listener) {
+  public SimpleUploadUtil(UploadTaskEntity taskEntity, IUploadListener listener) {
     mTaskEntity = taskEntity;
     CheckUtil.checkTaskEntity(taskEntity);
     mUploadEntity = taskEntity.getEntity();
@@ -45,6 +45,7 @@ public class SimpleHttpUploadUtil implements IUtil, Runnable {
   }
 
   @Override public void run() {
+    mListener.onPre();
     mUploader.start();
   }
 
@@ -69,7 +70,7 @@ public class SimpleHttpUploadUtil implements IUtil, Runnable {
   }
 
   @Override public void start() {
-    mUploader.start();
+    new Thread(this).start();
   }
 
   @Override public void resume() {
diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/Uploader.java b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/Uploader.java
index d09f5df4..8ef19e82 100644
--- a/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/Uploader.java
+++ b/Aria/src/main/java/com/arialyy/aria/core/upload/uploader/Uploader.java
@@ -47,14 +47,14 @@ class Uploader extends AbsFileer<UploadEntity, UploadTaskEntity> {
    * 5、不支持断点,则是新任务
    */
   protected void checkTask() {
-    if (!mTaskEntity.isSupportBP) {
-      isNewTask = true;
-      return;
-    }
     mConfigFile = new File(mContext.getFilesDir().getPath()
         + AriaManager.UPLOAD_TEMP_DIR
         + mEntity.getFileName()
         + ".properties");
+    if (!mTaskEntity.isSupportBP) {
+      isNewTask = true;
+      return;
+    }
     if (!mConfigFile.exists()) { //记录文件被删除,则重新下载
       isNewTask = true;
       CommonUtil.createFile(mConfigFile.getPath());
@@ -70,7 +70,7 @@ class Uploader extends AbsFileer<UploadEntity, UploadTaskEntity> {
 
   }
 
-  @Override protected int getThreadNum() {
+  @Override protected int getNewTaskThreadNum() {
     return 1;
   }
 
diff --git a/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java b/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java
index 2a941bae..3e6b6e54 100644
--- a/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java
+++ b/Aria/src/main/java/com/arialyy/aria/util/CommonUtil.java
@@ -150,7 +150,7 @@ public class CommonUtil {
   /**
    * 删除上传任务的配置,包括
    *
-   * @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经下载完成的文件
+   * @param removeFile {@code true} 不仅删除任务数据库记录,还会删除已经删除完成的文件
    * {@code false}如果任务已经完成,只删除任务数据库记录
    */
   public static void delUploadTaskConfig(boolean removeFile, UploadTaskEntity tEntity) {
@@ -160,15 +160,8 @@ public class CommonUtil {
       if (file.exists()) {
         file.delete();
       }
-    } else {
-      if (!uEntity.isComplete()) {
-        if (file.exists()) {
-          file.delete();
-        }
-      }
     }
-    File config = new File(
-        AriaManager.APP.getFilesDir().getPath() + "/temp/" + uEntity.getFileName() + ".properties");
+    File config = new File(getFileConfig(false, uEntity.getFileName()));
     if (config.exists()) {
       config.delete();
     }
@@ -197,8 +190,7 @@ public class CommonUtil {
       }
     }
 
-    File config = new File(
-        AriaManager.APP.getFilesDir().getPath() + "/temp/" + dEntity.getFileName() + ".properties");
+    File config = new File(getFileConfig(true, dEntity.getFileName()));
     if (config.exists()) {
       config.delete();
     }
diff --git a/AriaAnnotations/src/main/java/com/arialyy/annotations/Upload.java b/AriaAnnotations/src/main/java/com/arialyy/annotations/Upload.java
index 609c6663..cc197f92 100644
--- a/AriaAnnotations/src/main/java/com/arialyy/annotations/Upload.java
+++ b/AriaAnnotations/src/main/java/com/arialyy/annotations/Upload.java
@@ -43,18 +43,12 @@ import java.lang.annotation.Target;
     String[] value() default { AriaConstance.NO_URL };
   }
 
-  /**
-   * 如果你在方法中添加{@code @Upload.onTaskPre}注解,在任务预处理完成时,Aria会调用该方法
-   */
-  @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onTaskPre {
-    String[] value() default { AriaConstance.NO_URL };
-  }
-
   /**
    * 如果你在方法中添加{@code @Upload.onTaskResume}注解,在任务恢复下载时,Aria会调用该方法
    */
-  //@Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) public @interface onTaskResume {
-  //}
+  @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onTaskResume {
+    String[] value() default { AriaConstance.NO_URL };
+  }
 
   /**
    * 如果你在方法中添加{@code @Upload.onTaskStart}注解,在任务开始下载时,Aria会调用该方法
@@ -101,8 +95,7 @@ import java.lang.annotation.Target;
   /**
    * 如果你在方法中添加{@code @Upload.onNoSupportBreakPoint}注解,如果该任务不支持断点,Aria会调用该方法
    */
-  @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD)
-  @interface onNoSupportBreakPoint {
+  @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onNoSupportBreakPoint {
     String[] value() default { AriaConstance.NO_URL };
   }
 }
diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/AriaProcessor.java b/AriaCompiler/src/main/java/com/arialyy/compiler/AriaProcessor.java
index 814c6945..72c4b985 100644
--- a/AriaCompiler/src/main/java/com/arialyy/compiler/AriaProcessor.java
+++ b/AriaCompiler/src/main/java/com/arialyy/compiler/AriaProcessor.java
@@ -70,8 +70,7 @@ import javax.lang.model.element.TypeElement;
     annotataions.add(Upload.onTaskCancel.class.getCanonicalName());
     annotataions.add(Upload.onTaskComplete.class.getCanonicalName());
     annotataions.add(Upload.onTaskFail.class.getCanonicalName());
-    annotataions.add(Upload.onTaskPre.class.getCanonicalName());
-    //annotataions.add(Upload.onTaskResume.class.getCanonicalName());
+    annotataions.add(Upload.onTaskResume.class.getCanonicalName());
     annotataions.add(Upload.onTaskRunning.class.getCanonicalName());
     annotataions.add(Upload.onTaskStart.class.getCanonicalName());
     annotataions.add(Upload.onTaskStop.class.getCanonicalName());
diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/ElementHandler.java b/AriaCompiler/src/main/java/com/arialyy/compiler/ElementHandler.java
index 5cbdd005..fa4ce99e 100644
--- a/AriaCompiler/src/main/java/com/arialyy/compiler/ElementHandler.java
+++ b/AriaCompiler/src/main/java/com/arialyy/compiler/ElementHandler.java
@@ -120,8 +120,7 @@ class ElementHandler {
     saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskComplete.class,
         ProxyConstance.TASK_COMPLETE);
     saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskFail.class, ProxyConstance.TASK_FAIL);
-    saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskPre.class, ProxyConstance.TASK_PRE);
-    //saveMethod(false, roundEnv, Upload.onTaskResume.class);
+    saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskResume.class, ProxyConstance.TASK_RESUME);
     saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskRunning.class, ProxyConstance.TASK_RUNNING);
     saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskStart.class, ProxyConstance.TASK_START);
     saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskStop.class, ProxyConstance.TASK_STOP);
@@ -484,10 +483,10 @@ class ElementHandler {
         values = method.getAnnotation(Upload.onPre.class).value();
         break;
       case ProxyConstance.TASK_PRE:
-        values = method.getAnnotation(Upload.onTaskPre.class).value();
+        //values = method.getAnnotation(Upload.onTaskPre.class).value();
         break;
       case ProxyConstance.TASK_RESUME:
-        //values = method.getAnnotation(Upload.onTaskResume.class).value();
+        values = method.getAnnotation(Upload.onTaskResume.class).value();
         break;
       case ProxyConstance.TASK_START:
         values = method.getAnnotation(Upload.onTaskStart.class).value();
diff --git a/AriaFtpPlug/src/androidTest/java/com/arialyy/ftpplug/ExampleInstrumentedTest.java b/AriaFtpPlug/src/androidTest/java/com/arialyy/ftpplug/ExampleInstrumentedTest.java
deleted file mode 100644
index 8a8cb2b7..00000000
--- a/AriaFtpPlug/src/androidTest/java/com/arialyy/ftpplug/ExampleInstrumentedTest.java
+++ /dev/null
@@ -1,24 +0,0 @@
-package com.arialyy.ftpplug;
-
-import android.content.Context;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.runner.AndroidJUnit4;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import static org.junit.Assert.*;
-
-/**
- * Instrumentation test, which will execute on an Android device.
- *
- * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
- */
-@RunWith(AndroidJUnit4.class) public class ExampleInstrumentedTest {
-  @Test public void useAppContext() throws Exception {
-    // Context of the app under test.
-    Context appContext = InstrumentationRegistry.getTargetContext();
-
-    assertEquals("com.arialyy.ftpplug.test", appContext.getPackageName());
-  }
-}
diff --git a/AriaFtpPlug/src/main/java/com/arialyy/ftpplug/Test.java b/AriaFtpPlug/src/main/java/com/arialyy/ftpplug/Test.java
deleted file mode 100644
index e6199b6a..00000000
--- a/AriaFtpPlug/src/main/java/com/arialyy/ftpplug/Test.java
+++ /dev/null
@@ -1,8 +0,0 @@
-package com.arialyy.ftpplug;
-
-/**
- * Created by Aria.Lao on 2017/7/24.
- */
-
-public class Test {
-}
diff --git a/AriaFtpPlug/src/test/java/com/arialyy/ftpplug/ExampleUnitTest.java b/AriaFtpPlug/src/test/java/com/arialyy/ftpplug/ExampleUnitTest.java
deleted file mode 100644
index 86bf986f..00000000
--- a/AriaFtpPlug/src/test/java/com/arialyy/ftpplug/ExampleUnitTest.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package com.arialyy.ftpplug;
-
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-/**
- * Example local unit test, which will execute on the development machine (host).
- *
- * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
- */
-public class ExampleUnitTest {
-  @Test public void addition_isCorrect() throws Exception {
-    assertEquals(4, 2 + 2);
-  }
-}
\ No newline at end of file
diff --git a/app/.gitignore b/app/.gitignore
index 796b96d1..fcd3a08d 100644
--- a/app/.gitignore
+++ b/app/.gitignore
@@ -1 +1,2 @@
 /build
+*.log
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index e79b82bb..3848e920 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -24,7 +24,6 @@
     </activity>
 
     <activity android:name=".download.DownloadActivity"/>
-    <activity android:name=".upload.UploadActivity"/>
     <activity android:name=".download.SingleTaskActivity"/>
     <activity android:name=".download.multi_download.MultiTaskActivity"/>
     <activity android:name=".download.fragment_download.FragmentActivity"/>
@@ -34,6 +33,7 @@
     <activity android:name=".download.group.DownloadGroupActivity"/>
     <activity android:name=".download.FtpDownloadActivity"/>
     <activity android:name=".download.group.FTPDirDownloadActivity"/>
+    <activity android:name=".upload.HttpUploadActivity"/>
     <activity android:name=".upload.FtpUploadActivity"/>
 
     <service android:name=".download.service_download.DownloadService"/>
diff --git a/app/src/main/assets/aria_config.xml b/app/src/main/assets/aria_config.xml
index bbda9fa1..621b0464 100644
--- a/app/src/main/assets/aria_config.xml
+++ b/app/src/main/assets/aria_config.xml
@@ -37,6 +37,8 @@
   </download>
 
   <upload>
+    <!--是否需要转换速度单位,转换完成后为:1b/s、1kb/s、1mb/s、1gb/s、1tb/s,如果不需要将返回byte长度-->
+    <convertSpeed value="true"/>
 
     <!--设置上传队列最大任务数, 默认为2-->
     <maxTaskNum value="2"/>
diff --git a/app/src/main/java/com/arialyy/simple/MainActivity.java b/app/src/main/java/com/arialyy/simple/MainActivity.java
index 50481142..8a8a7cd6 100644
--- a/app/src/main/java/com/arialyy/simple/MainActivity.java
+++ b/app/src/main/java/com/arialyy/simple/MainActivity.java
@@ -27,7 +27,7 @@ import com.arialyy.simple.download.FtpDownloadActivity;
 import com.arialyy.simple.download.group.DownloadGroupActivity;
 import com.arialyy.simple.download.group.FTPDirDownloadActivity;
 import com.arialyy.simple.upload.FtpUploadActivity;
-import com.arialyy.simple.upload.UploadActivity;
+import com.arialyy.simple.upload.HttpUploadActivity;
 
 /**
  * Created by Aria.Lao on 2017/3/1.
@@ -54,7 +54,7 @@ public class MainActivity extends BaseActivity<ActivityMainBinding> {
         startActivity(new Intent(this, DownloadActivity.class));
         break;
       case R.id.upload:
-        startActivity(new Intent(this, UploadActivity.class));
+        startActivity(new Intent(this, HttpUploadActivity.class));
         break;
       case R.id.download_task_group:
         startActivity(new Intent(this, DownloadGroupActivity.class));
diff --git a/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java b/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java
index 710f3a79..ae725295 100644
--- a/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java
+++ b/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java
@@ -185,17 +185,6 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
   public void onClick(View view) {
     switch (view.getId()) {
       case R.id.start:
-        //String text = ((TextView) view).getText().toString();
-        //if (text.equals("重新开始?") || text.equals("开始")) {
-        //  Aria.download(this)
-        //      .load(URL)
-        //      .addHeader("groupName", "value")
-        //      .setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/test.apk")
-        //      .setFileName("hehe.apk")
-        //      .start();
-        //} else if (text.equals("恢复")) {
-        //  Aria.download(this).load(URL).resume();
-        //}
         Aria.download(this)
             .load(DOWNLOAD_URL)
             .addHeader("groupName", "value")
diff --git a/app/src/main/java/com/arialyy/simple/upload/FtpUploadActivity.java b/app/src/main/java/com/arialyy/simple/upload/FtpUploadActivity.java
index 8a9dbe1d..f8d6492e 100644
--- a/app/src/main/java/com/arialyy/simple/upload/FtpUploadActivity.java
+++ b/app/src/main/java/com/arialyy/simple/upload/FtpUploadActivity.java
@@ -20,7 +20,9 @@ import android.util.Log;
 import android.view.View;
 import com.arialyy.annotations.Upload;
 import com.arialyy.aria.core.Aria;
+import com.arialyy.aria.core.upload.UploadEntity;
 import com.arialyy.aria.core.upload.UploadTask;
+import com.arialyy.aria.util.CommonUtil;
 import com.arialyy.frame.util.show.L;
 import com.arialyy.frame.util.show.T;
 import com.arialyy.simple.R;
@@ -32,12 +34,19 @@ import com.arialyy.simple.databinding.ActivityFtpUploadBinding;
  * Ftp 文件上传demo
  */
 public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
-  private final String FILE_PATH = "/mnt/sdcard/王者军团.apk";
+  private final String FILE_PATH = "/mnt/sdcard/gggg.apk";
   private final String URL = "ftp://172.18.104.129:21/upload/";
 
   @Override protected void init(Bundle savedInstanceState) {
+    setTile("FTP 文件上传");
     super.init(savedInstanceState);
     Aria.upload(this).register();
+    UploadEntity entity = Aria.upload(this).getUploadEntity(FILE_PATH);
+    if (entity != null) {
+      getBinding().setFileSize(CommonUtil.formatFileSize(entity.getFileSize()));
+      getBinding().setProgress(entity.isComplete() ? 100
+          : (int) (entity.getCurrentProgress() * 100 / entity.getFileSize()));
+    }
   }
 
   @Override protected int setLayoutId() {
@@ -53,7 +62,7 @@ public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
         Aria.upload(this).loadFtp(FILE_PATH).stop();
         break;
       case R.id.cancel:
-        Aria.upload(this).load(FILE_PATH).cancel();
+        Aria.upload(this).loadFtp(FILE_PATH).cancel();
         break;
     }
   }
@@ -62,12 +71,12 @@ public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
     getBinding().setFileSize(task.getConvertFileSize());
   }
 
-  @Upload.onTaskPre public void taskPre(UploadTask task) {
-    L.d(TAG, "fileSize = " + task.getConvertFileSize());
+  @Upload.onTaskStart public void taskStart(UploadTask task) {
+    Log.d(TAG, "开始上传");
   }
 
-  @Upload.onTaskStart public void taskStart(UploadTask task) {
-
+  @Upload.onTaskResume public void taskResume(UploadTask task) {
+    Log.d(TAG, "恢复上传");
   }
 
   @Upload.onTaskStop public void taskStop(UploadTask task) {
@@ -77,7 +86,9 @@ public class FtpUploadActivity extends BaseActivity<ActivityFtpUploadBinding> {
 
   @Upload.onTaskCancel public void taskCancel(UploadTask task) {
     getBinding().setSpeed("");
-    Log.d(TAG, "取消上传");
+    getBinding().setFileSize("");
+    getBinding().setProgress(0);
+    Log.d(TAG, "删除任务");
   }
 
   @Upload.onTaskRunning public void taskRunning(UploadTask task) {
diff --git a/app/src/main/java/com/arialyy/simple/upload/UploadActivity.java b/app/src/main/java/com/arialyy/simple/upload/HttpUploadActivity.java
similarity index 56%
rename from app/src/main/java/com/arialyy/simple/upload/UploadActivity.java
rename to app/src/main/java/com/arialyy/simple/upload/HttpUploadActivity.java
index 1d9eb32b..e8a1b419 100644
--- a/app/src/main/java/com/arialyy/simple/upload/UploadActivity.java
+++ b/app/src/main/java/com/arialyy/simple/upload/HttpUploadActivity.java
@@ -17,16 +17,12 @@
 package com.arialyy.simple.upload;
 
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Message;
 import butterknife.Bind;
 import butterknife.OnClick;
 import com.arialyy.annotations.Upload;
 import com.arialyy.aria.core.Aria;
 import com.arialyy.aria.core.upload.UploadTask;
-import com.arialyy.frame.util.FileUtil;
 import com.arialyy.frame.util.show.L;
-import com.arialyy.frame.util.show.T;
 import com.arialyy.simple.R;
 import com.arialyy.simple.base.BaseActivity;
 import com.arialyy.simple.databinding.ActivityUploadBinding;
@@ -35,50 +31,19 @@ import com.arialyy.simple.widget.HorizontalProgressBarWithNumber;
 /**
  * Created by Aria.Lao on 2017/2/9.
  */
-public class UploadActivity extends BaseActivity<ActivityUploadBinding> {
-  private static final String TAG = "UploadActivity";
+public class HttpUploadActivity extends BaseActivity<ActivityUploadBinding> {
+  private static final String TAG = "HttpUploadActivity";
   @Bind(R.id.pb) HorizontalProgressBarWithNumber mPb;
-  private static final int START = 0;
-  private static final int STOP = 1;
-  private static final int CANCEL = 2;
-  private static final int RUNNING = 3;
-  private static final int COMPLETE = 4;
 
-  private static final String FILE_PATH = "/sdcard/Download/test.zip";
-
-  private Handler mHandler = new Handler() {
-    @Override public void handleMessage(Message msg) {
-      super.handleMessage(msg);
-      UploadTask task = (UploadTask) msg.obj;
-      switch (msg.what) {
-        case START:
-          getBinding().setFileSize(FileUtil.formatFileSize(task.getFileSize()));
-          break;
-        case STOP:
-          mPb.setProgress(0);
-          break;
-        case CANCEL:
-          mPb.setProgress(0);
-          break;
-        case RUNNING:
-          int p = (int) (task.getCurrentProgress() * 100 / task.getFileSize());
-          mPb.setProgress(p);
-          break;
-        case COMPLETE:
-          T.showShort(UploadActivity.this, "上传完成");
-          mPb.setProgress(100);
-          break;
-      }
-    }
-  };
+  private static final String FILE_PATH = "/sdcard/large.rar";
 
   @Override protected int setLayoutId() {
     return R.layout.activity_upload;
   }
 
   @Override protected void init(Bundle savedInstanceState) {
+    setTile("HTTP 上传");
     super.init(savedInstanceState);
-    setTile("http上传");
     Aria.upload(this).register();
   }
 
@@ -101,27 +66,31 @@ public class UploadActivity extends BaseActivity<ActivityUploadBinding> {
   @Upload.onPre public void onPre(UploadTask task) {
   }
 
-  @Upload.onTaskPre public void taskPre(UploadTask task) {
-    L.d(TAG, "fileSize = " + task.getConvertFileSize());
-  }
-
   @Upload.onTaskStart public void taskStart(UploadTask task) {
-    mHandler.obtainMessage(START, task).sendToTarget();
+    L.d(TAG, "upload start");
+    getBinding().setFileSize(task.getConvertFileSize());
   }
 
   @Upload.onTaskStop public void taskStop(UploadTask task) {
-    mHandler.obtainMessage(STOP, task).sendToTarget();
+    L.d(TAG, "upload stop");
+    getBinding().setSpeed("");
+    getBinding().setProgress(0);
   }
 
   @Upload.onTaskCancel public void taskCancel(UploadTask task) {
-    mHandler.obtainMessage(CANCEL, task).sendToTarget();
+    L.d(TAG, "upload cancel");
+    getBinding().setSpeed("");
+    getBinding().setProgress(0);
   }
 
   @Upload.onTaskRunning public void taskRunning(UploadTask task) {
-    mHandler.obtainMessage(RUNNING, task).sendToTarget();
+    getBinding().setSpeed(task.getConvertSpeed());
+    getBinding().setProgress(task.getPercent());
   }
 
   @Upload.onTaskComplete public void taskComplete(UploadTask task) {
-    mHandler.obtainMessage(COMPLETE, task).sendToTarget();
+    L.d(TAG, "上传完成");
+    getBinding().setSpeed("");
+    getBinding().setProgress(100);
   }
 }
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index de9a5c45..177b1590 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -13,7 +13,7 @@
         android:id="@+id/download"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="下载"
+        android:text="http 下载"
         style="?buttonBarButtonStyle"
         />
 
@@ -21,7 +21,7 @@
         android:id="@+id/upload"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="上传"
+        android:text="http 上传"
         style="?buttonBarButtonStyle"
         />
 
@@ -29,7 +29,7 @@
         android:id="@+id/download_task_group"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:text="下载任务组"
+        android:text="http 下载任务组"
         style="?buttonBarButtonStyle"
         />
 
diff --git a/app/src/main/res/layout/activity_upload.xml b/app/src/main/res/layout/activity_upload.xml
index 552addf5..425c9ea3 100644
--- a/app/src/main/res/layout/activity_upload.xml
+++ b/app/src/main/res/layout/activity_upload.xml
@@ -11,6 +11,11 @@
         type="String"
         />
 
+    <variable
+        name="progress"
+        type="int"
+        />
+
   </data>
 
   <LinearLayout
@@ -34,6 +39,7 @@
           android:layout_margin="16dp"
           android:layout_toLeftOf="@+id/size"
           android:max="100"
+          android:progress="@{progress}"
           style="?android:attr/progressBarStyleHorizontal"
           />
 
diff --git a/aria/src/main/java/com/arialyy/aria/core/upload/UploadTask.java b/aria/src/main/java/com/arialyy/aria/core/upload/UploadTask.java
index 8c66dd4a..d9e182ee 100644
--- a/aria/src/main/java/com/arialyy/aria/core/upload/UploadTask.java
+++ b/aria/src/main/java/com/arialyy/aria/core/upload/UploadTask.java
@@ -15,16 +15,12 @@
  */
 package com.arialyy.aria.core.upload;
 
-import android.content.Context;
 import android.os.Handler;
 import android.util.Log;
-import com.arialyy.aria.core.AriaManager;
 import com.arialyy.aria.core.inf.AbsNormalTask;
 import com.arialyy.aria.core.inf.IEntity;
 import com.arialyy.aria.core.scheduler.ISchedulers;
-import com.arialyy.aria.core.upload.uploader.SimpleHttpUploadUtil;
-import com.arialyy.aria.util.CommonUtil;
-import java.lang.ref.WeakReference;
+import com.arialyy.aria.core.upload.uploader.SimpleUploadUtil;
 
 /**
  * Created by lyy on 2017/2/23.
@@ -33,14 +29,14 @@ import java.lang.ref.WeakReference;
 public class UploadTask extends AbsNormalTask<UploadEntity> {
   private static final String TAG = "UploadTask";
 
-  private SimpleHttpUploadUtil mUtil;
-  private UListener mListener;
+  private SimpleUploadUtil mUtil;
+  private BaseUListener<UploadEntity, UploadTask> mListener;
 
   private UploadTask(UploadTaskEntity taskEntity, Handler outHandler) {
     mOutHandler = outHandler;
     mEntity = taskEntity.getEntity();
-    mListener = new UListener(mOutHandler, this);
-    mUtil = new SimpleHttpUploadUtil(taskEntity, mListener);
+    mListener = new BaseUListener<>(this, mOutHandler);
+    mUtil = new SimpleUploadUtil(taskEntity, mListener);
   }
 
   @Override public String getKey() {
@@ -55,9 +51,6 @@ public class UploadTask extends AbsNormalTask<UploadEntity> {
     if (mUtil.isRunning()) {
       Log.d(TAG, "任务正在下载");
     } else {
-      if (mListener == null) {
-        mListener = new UploadTask.UListener(mOutHandler, this);
-      }
       mUtil.start();
     }
   }
@@ -75,119 +68,12 @@ public class UploadTask extends AbsNormalTask<UploadEntity> {
   }
 
   @Override public void cancel() {
-
-    if (!mEntity.isComplete()) {
-      // 如果任务不是下载状态
-      mUtil.cancel();
-      mEntity.deleteData();
+    if (!mUtil.isRunning()) {
       if (mOutHandler != null) {
         mOutHandler.obtainMessage(ISchedulers.CANCEL, this).sendToTarget();
       }
     }
-  }
-
-  private static class UListener extends UploadListener {
-    WeakReference<Handler> outHandler;
-    WeakReference<UploadTask> task;
-    long lastLen = 0;   //上一次发送长度
-    long lastTime = 0;
-    long INTERVAL_TIME = 1000;   //1m更新周期
-    boolean isFirst = true;
-    UploadEntity entity;
-    boolean isConvertSpeed = false;
-    Context context;
-
-    UListener(Handler outHandle, UploadTask task) {
-      this.outHandler = new WeakReference<>(outHandle);
-      this.task = new WeakReference<>(task);
-      entity = this.task.get().getEntity();
-      context = AriaManager.APP;
-      final AriaManager manager = AriaManager.getInstance(context);
-      isConvertSpeed = manager.getUploadConfig().isConvertSpeed();
-    }
-
-    @Override public void onPre() {
-      sendInState2Target(ISchedulers.PRE);
-      saveData(IEntity.STATE_PRE, -1);
-    }
-
-    @Override public void onStart(long startLocation) {
-      sendInState2Target(ISchedulers.START);
-      saveData(IEntity.STATE_RUNNING, 0);
-    }
-
-    @Override public void onResume(long resumeLocation) {
-      sendInState2Target(ISchedulers.RESUME);
-      saveData(IEntity.STATE_RUNNING, resumeLocation);
-    }
-
-    @Override public void onStop(long stopLocation) {
-      handleSpeed(0);
-      sendInState2Target(ISchedulers.STOP);
-      saveData(IEntity.STATE_STOP, stopLocation);
-    }
-
-    @Override public void onProgress(long currentLocation) {
-      if (System.currentTimeMillis() - lastTime > INTERVAL_TIME) {
-        long speed = currentLocation - lastLen;
-        lastTime = System.currentTimeMillis();
-        if (isFirst) {
-          speed = 0;
-          isFirst = false;
-        }
-        handleSpeed(speed);
-        entity.setCurrentProgress(currentLocation);
-        lastLen = currentLocation;
-        sendInState2Target(ISchedulers.RUNNING);
-      }
-    }
-
-    @Override public void onCancel() {
-      handleSpeed(0);
-      sendInState2Target(ISchedulers.CANCEL);
-      saveData(IEntity.STATE_CANCEL, -1);
-      entity.deleteData();
-    }
-
-    @Override public void onComplete() {
-      entity.setComplete(true);
-      handleSpeed(0);
-      sendInState2Target(ISchedulers.COMPLETE);
-      saveData(IEntity.STATE_COMPLETE, entity.getFileSize());
-    }
-
-    @Override public void onFail() {
-      entity.setFailNum(entity.getFailNum() + 1);
-      handleSpeed(0);
-      sendInState2Target(ISchedulers.FAIL);
-      saveData(IEntity.STATE_FAIL, -1);
-    }
-
-    private void handleSpeed(long speed) {
-      if (isConvertSpeed) {
-        entity.setConvertSpeed(CommonUtil.formatFileSize(speed) + "/s");
-      } else {
-        entity.setSpeed(speed);
-      }
-    }
-
-    /**
-     * 将任务状态发送给下载器
-     *
-     * @param state {@link ISchedulers#START}
-     */
-    private void sendInState2Target(int state) {
-      if (outHandler.get() != null) {
-        outHandler.get().obtainMessage(state, task.get()).sendToTarget();
-      }
-    }
-
-    private void saveData(int state, long location) {
-      entity.setState(state);
-      entity.setComplete(state == IEntity.STATE_COMPLETE);
-      entity.setCurrentProgress(location);
-      entity.update();
-    }
+    mUtil.cancel();
   }
 
   public static class Builder {