diff --git a/FtpComponent/src/main/java/com/arialyy/aria/ftp/AbsFtpInfoTask.java b/FtpComponent/src/main/java/com/arialyy/aria/ftp/AbsFtpInfoTask.java index 588df77b..321a36f7 100644 --- a/FtpComponent/src/main/java/com/arialyy/aria/ftp/AbsFtpInfoTask.java +++ b/FtpComponent/src/main/java/com/arialyy/aria/ftp/AbsFtpInfoTask.java @@ -37,7 +37,6 @@ import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.CheckUtil; import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.SSLContextUtil; -import java.io.File; import java.io.IOException; import java.net.InetAddress; import java.net.UnknownHostException; @@ -57,7 +56,6 @@ public abstract class AbsFtpInfoTask 0) { - ALog.i(TAG, - String.format("路径【%s】下的文件列表 ===================================", getRemotePath())); - for (FTPFile file : files1) { - ALog.d(TAG, file.toString()); - } - ALog.i(TAG, - "================================= --end-- ==================================="); - } else { - ALog.w(TAG, String.format("获取文件列表失败,msg:%s", client.getReplyString())); - } - closeClient(client); - - failDownload(client, - String.format("文件不存在,url: %s, remotePath:%s", mTaskOption.getUrlEntity().url, - remotePath), null, false); - return; - } - - // 处理拦截功能 - if (!onInterceptor(client, files)) { - closeClient(client); - ALog.d(TAG, "拦截器处理完成任务"); - return; - } - - //为了防止编码错乱,需要使用原始字符串 - if (isUpload && files.length == 0){ - handleFile(getRemotePath(), null); - }else { - mSize = getFileSize(files, client, getRemotePath()); - } - int reply = client.getReplyCode(); - if (!FTPReply.isPositiveCompletion(reply)) { - if (isUpload) { - //服务器上没有该文件路径,表示该任务为新的上传任务 - mTaskWrapper.setNewTask(true); - } else { - closeClient(client); - failDownload(client, "获取文件信息错误,url: " + mTaskOption.getUrlEntity().url, null, true); - return; - } - } - mTaskWrapper.setCode(reply); - if (mSize != 0 && !isUpload) { - mEntity.setFileSize(mSize); - } - onPreComplete(reply); - mEntity.update(); + String convertedRemotePath = CommonUtil.convertFtpChar(charSet, getRemotePath()); + FTPFile[] files = client.listFiles(convertedRemotePath); + handelFileInfo(client, files, convertedRemotePath); } catch (IOException e) { e.printStackTrace(); failDownload(client, "FTP错误信息", e, true); @@ -171,20 +121,6 @@ public abstract class AbsFtpInfoTask 0) { + ALog.i(TAG, + String.format("路径【%s】下的文件列表 ===================================", getRemotePath())); + for (FTPFile file : files1) { + ALog.d(TAG, file.toString()); + } + ALog.i(TAG, + "================================= --end-- ==================================="); + } else { + ALog.w(TAG, String.format("获取文件列表失败,msg:%s", client.getReplyString())); + } + closeClient(client); + + failDownload(client, + String.format("文件不存在,url: %s, remotePath:%s", mTaskOption.getUrlEntity().url, + getRemotePath()), null, false); + return; + } + + // 处理拦截功能 + if (!onInterceptor(client, files)) { + closeClient(client); + ALog.d(TAG, "拦截器处理完成任务"); + return; + } + + //为了防止编码错乱,需要使用原始字符串 + mSize = getFileSize(files, client, getRemotePath()); + int reply = client.getReplyCode(); + if (!FTPReply.isPositiveCompletion(reply)) { + closeClient(client); + failDownload(client, "获取文件信息错误,url: " + mTaskOption.getUrlEntity().url, null, true); + return; + } + mTaskWrapper.setCode(reply); + if (mSize != 0) { + mEntity.setFileSize(mSize); + } + onPreComplete(reply); + mEntity.update(); + } + @Override protected String getRemotePath() { return mTaskOption.getUrlEntity().remotePath; } diff --git a/FtpComponent/src/main/java/com/arialyy/aria/ftp/download/FtpDGInfoTask.java b/FtpComponent/src/main/java/com/arialyy/aria/ftp/download/FtpDGInfoTask.java index 27411f04..7dbf2132 100644 --- a/FtpComponent/src/main/java/com/arialyy/aria/ftp/download/FtpDGInfoTask.java +++ b/FtpComponent/src/main/java/com/arialyy/aria/ftp/download/FtpDGInfoTask.java @@ -19,6 +19,7 @@ import android.net.Uri; import android.text.TextUtils; import aria.apache.commons.net.ftp.FTPClient; import aria.apache.commons.net.ftp.FTPFile; +import aria.apache.commons.net.ftp.FTPReply; import com.arialyy.aria.core.FtpUrlEntity; import com.arialyy.aria.core.common.CompleteInfo; import com.arialyy.aria.core.download.DGTaskWrapper; @@ -32,6 +33,8 @@ import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.util.ALog; import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.RecordUtil; +import java.io.File; +import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; @@ -52,6 +55,60 @@ final class FtpDGInfoTask extends AbsFtpInfoTask 0) { + ALog.i(TAG, + String.format("路径【%s】下的文件列表 ===================================", getRemotePath())); + for (FTPFile file : files1) { + ALog.d(TAG, file.toString()); + } + ALog.i(TAG, + "================================= --end-- ==================================="); + } else { + ALog.w(TAG, String.format("获取文件列表失败,msg:%s", client.getReplyString())); + } + closeClient(client); + + failDownload(client, + String.format("文件不存在,url: %s, remotePath:%s", mTaskOption.getUrlEntity().url, + getRemotePath()), null, false); + return; + } + + // 处理拦截功能 + if (!onInterceptor(client, files)) { + closeClient(client); + ALog.d(TAG, "拦截器处理完成任务"); + return; + } + + //为了防止编码错乱,需要使用原始字符串 + mSize = getFileSize(files, client, getRemotePath()); + int reply = client.getReplyCode(); + if (!FTPReply.isPositiveCompletion(reply)) { + closeClient(client); + failDownload(client, "获取文件信息错误,url: " + mTaskOption.getUrlEntity().url, null, true); + return; + } + mTaskWrapper.setCode(reply); + if (mSize != 0) { + mEntity.setFileSize(mSize); + } + onPreComplete(reply); + mEntity.update(); + } + /** * 检查子任务的任务设置 * @@ -110,7 +167,7 @@ final class FtpDGInfoTask extends AbsFtpInfoTask ALog.d(TAG, String.format("删除文件%s,code: %s, msg: %s", b ? "成功" : "失败", client.getReplyCode(), client.getReplyString())); - mTaskOption.setServeFileIsExist(false); } else if (!TextUtils.isEmpty(interceptHandler.getNewFileName())) { ALog.i(TAG, String.format("远端已拥有同名文件,将修改remotePath,原文件名:%s,新文件名:%s", mEntity.getFileName(), interceptHandler.getNewFileName())); @@ -95,7 +114,6 @@ final class FtpUFileInfoTask extends AbsFtpInfoTask + interceptHandler.getNewFileName(); mTaskOption.setNewFileName(interceptHandler.getNewFileName()); - mTaskOption.setServeFileIsExist(false); closeClient(client); run(); return false; @@ -120,84 +138,16 @@ final class FtpUFileInfoTask extends AbsFtpInfoTask */ @Override protected void handleFile(String remotePath, FTPFile ftpFile) { super.handleFile(remotePath, ftpFile); - if (ftpFile != null) { - //远程文件已完成 - if (ftpFile.getSize() == mEntity.getFileSize()) { - isComplete = true; - ALog.d(TAG, "FTP服务器上已存在该文件【" + ftpFile.getName() + "】"); - } else if (ftpFile.getSize() == 0) { - mTaskWrapper.setNewTask(true); - ALog.d(TAG, "FTP服务器上已存在该文件【" + ftpFile.getName() + "】,但文件长度为0,重新上传该文件"); - } else { - ALog.w(TAG, "FTP服务器已存在未完成的文件【" - + ftpFile.getName() - + ",size: " - + ftpFile.getSize() - + "】" - + "尝试从位置:" - + (ftpFile.getSize() - 1) - + "开始上传"); - mTaskWrapper.setNewTask(false); - - // 修改记录 - TaskRecord record = DbDataHelper.getTaskRecord(mTaskWrapper.getKey(), - mTaskWrapper.getEntity().getTaskType()); - if (record == null) { - record = new TaskRecord(); - record.fileName = mEntity.getFileName(); - record.filePath = mTaskWrapper.getKey(); - record.threadRecords = new ArrayList<>(); - } - ThreadRecord threadRecord; - if (record.threadRecords == null || record.threadRecords.isEmpty()) { - threadRecord = new ThreadRecord(); - threadRecord.taskKey = record.filePath; - } else { - threadRecord = record.threadRecords.get(0); - } - //修改本地保存的停止地址为服务器上对应文件的大小 - threadRecord.startLocation = ftpFile.getSize() - 1; - record.save(); - threadRecord.save(); - } - }else { - ALog.d(TAG, "FTP服务器上不存在该文件"); - mTaskWrapper.setNewTask(false); - TaskRecord record = DbDataHelper.getTaskRecord(mTaskWrapper.getKey(), - mTaskWrapper.getEntity().getTaskType()); - if (record != null){ - ALog.w(TAG, String.format("任务记录【%s】已存在,将删除该记录", mTaskWrapper.getKey())); - delTaskRecord(record); - } - mTaskWrapper.setNewTask(true); - record = new TaskRecord(); - record.fileName = mEntity.getFileName(); - record.filePath = mTaskWrapper.getKey(); - record.threadRecords = new ArrayList<>(); - ThreadRecord threadRecord = new ThreadRecord(); - threadRecord.taskKey = record.filePath; - threadRecord.startLocation = 0; - threadRecord.endLocation = mEntity.getFileSize(); - threadRecord.isComplete = false; - - record.save(); - threadRecord.save(); - } - } - - private void delTaskRecord(TaskRecord record){ - List threadRecords = record.threadRecords; - if (threadRecords != null && !threadRecords.isEmpty()){ - for (ThreadRecord tr : threadRecords){ - tr.deleteData(); - } + this.ftpFile = ftpFile; + if (ftpFile != null && ftpFile.getSize() == mEntity.getFileSize()) { + isComplete = true; } - record.deleteData(); } @Override protected void onPreComplete(int code) { super.onPreComplete(code); - callback.onSucceed(mEntity.getKey(), - new CompleteInfo(isComplete ? CODE_COMPLETE : code, mTaskWrapper)); + CompleteInfo info = new CompleteInfo(isComplete ? CODE_COMPLETE : code, mTaskWrapper); + info.obj = ftpFile; + callback.onSucceed(mEntity.getKey(), info); } } diff --git a/FtpComponent/src/main/java/com/arialyy/aria/ftp/upload/FtpULoader.java b/FtpComponent/src/main/java/com/arialyy/aria/ftp/upload/FtpULoader.java index 21076650..442e7e67 100644 --- a/FtpComponent/src/main/java/com/arialyy/aria/ftp/upload/FtpULoader.java +++ b/FtpComponent/src/main/java/com/arialyy/aria/ftp/upload/FtpULoader.java @@ -15,19 +15,56 @@ */ package com.arialyy.aria.ftp.upload; +import android.os.Handler; +import aria.apache.commons.net.ftp.FTPFile; import com.arialyy.aria.core.common.AbsEntity; import com.arialyy.aria.core.common.CompleteInfo; import com.arialyy.aria.core.listener.IEventListener; import com.arialyy.aria.core.loader.IInfoTask; +import com.arialyy.aria.core.loader.IRecordHandler; import com.arialyy.aria.core.loader.NormalLoader; +import com.arialyy.aria.core.manager.ThreadTaskManager; +import com.arialyy.aria.core.task.IThreadTask; import com.arialyy.aria.core.wrapper.AbsTaskWrapper; import com.arialyy.aria.exception.BaseException; final class FtpULoader extends NormalLoader { + private FTPFile ftpFile; + FtpULoader(AbsTaskWrapper wrapper, IEventListener listener) { super(wrapper, listener); } + @Override + protected void startThreadTask() { + // 检查记录 + ((FtpURecordHandler) mRecordHandler).setFtpFile(ftpFile); + if (mRecordHandler.checkTaskCompleted()) { + mRecord.deleteData(); + isComplete = true; + getListener().onComplete(); + return; + } + mRecord = mRecordHandler.getRecord(getFileSize()); + + // 初始化线程状态管理器 + mStateManager.setLooper(mRecord, getLooper()); + getTaskList().addAll(mTTBuilder.buildThreadTask(mRecord, + new Handler(getLooper(), mStateManager.getHandlerCallback()))); + mStateManager.updateCurrentProgress(getEntity().getCurrentProgress()); + + if (mStateManager.getCurrentProgress() > 0) { + getListener().onResume(mStateManager.getCurrentProgress()); + } else { + getListener().onStart(mStateManager.getCurrentProgress()); + } + + // 启动线程任务 + for (IThreadTask threadTask : getTaskList()) { + ThreadTaskManager.getInstance().startThread(mTaskWrapper.getKey(), threadTask); + } + } + @Override public void addComponent(IInfoTask infoTask) { mInfoTask = infoTask; infoTask.setCallback(new IInfoTask.Callback() { @@ -35,6 +72,7 @@ final class FtpULoader extends NormalLoader { if (info.code == FtpUFileInfoTask.CODE_COMPLETE) { getListener().onComplete(); } else { + ftpFile = (FTPFile) info.obj; startThreadTask(); } } @@ -44,4 +82,8 @@ final class FtpULoader extends NormalLoader { } }); } + + @Override public void addComponent(IRecordHandler recordHandler) { + mRecordHandler = recordHandler; + } } diff --git a/FtpComponent/src/main/java/com/arialyy/aria/ftp/upload/FtpULoaderUtil.java b/FtpComponent/src/main/java/com/arialyy/aria/ftp/upload/FtpULoaderUtil.java index b8fe8589..a1295fb6 100644 --- a/FtpComponent/src/main/java/com/arialyy/aria/ftp/upload/FtpULoaderUtil.java +++ b/FtpComponent/src/main/java/com/arialyy/aria/ftp/upload/FtpULoaderUtil.java @@ -22,7 +22,6 @@ import com.arialyy.aria.core.loader.LoaderStructure; import com.arialyy.aria.core.loader.NormalThreadStateManager; import com.arialyy.aria.core.upload.UTaskWrapper; import com.arialyy.aria.core.wrapper.AbsTaskWrapper; -import com.arialyy.aria.ftp.FtpRecordHandler; import com.arialyy.aria.ftp.FtpTaskOption; /** @@ -42,7 +41,7 @@ public final class FtpULoaderUtil extends AbsNormalLoaderUtil { @Override public LoaderStructure BuildLoaderStructure() { LoaderStructure structure = new LoaderStructure(); - structure.addComponent(new FtpRecordHandler(getTaskWrapper())) + structure.addComponent(new FtpURecordHandler((UTaskWrapper) getTaskWrapper())) .addComponent(new NormalThreadStateManager(getListener())) .addComponent(new FtpUFileInfoTask((UTaskWrapper) getTaskWrapper())) .addComponent(new FtpUTTBuilder(getTaskWrapper())); diff --git a/FtpComponent/src/main/java/com/arialyy/aria/ftp/upload/FtpURecordHandler.java b/FtpComponent/src/main/java/com/arialyy/aria/ftp/upload/FtpURecordHandler.java new file mode 100644 index 00000000..aa452338 --- /dev/null +++ b/FtpComponent/src/main/java/com/arialyy/aria/ftp/upload/FtpURecordHandler.java @@ -0,0 +1,112 @@ +/* + * 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.ftp.upload; + +import aria.apache.commons.net.ftp.FTPFile; +import com.arialyy.aria.core.TaskRecord; +import com.arialyy.aria.core.ThreadRecord; +import com.arialyy.aria.core.common.RecordHandler; +import com.arialyy.aria.core.upload.UTaskWrapper; +import com.arialyy.aria.util.ALog; +import com.arialyy.aria.util.RecordUtil; +import java.util.ArrayList; + +/** + * 上传任务记录处理器 + */ +final class FtpURecordHandler extends RecordHandler { + private FTPFile ftpFile; + + FtpURecordHandler(UTaskWrapper wrapper) { + super(wrapper); + } + + void setFtpFile(FTPFile ftpFile) { + this.ftpFile = ftpFile; + } + + @Override public void handlerTaskRecord(TaskRecord record) { + if (record.threadRecords == null || record.threadRecords.isEmpty()) { + record.threadRecords = new ArrayList<>(); + record.threadRecords.add( + createThreadRecord(record, 0, ftpFile == null ? 0 : ftpFile.getSize(), getFileSize())); + } + + if (ftpFile != null) { + //远程文件已完成 + if (ftpFile.getSize() == getFileSize()) { + record.threadRecords.get(0).isComplete = true; + ALog.d(TAG, "FTP服务器上已存在该文件【" + ftpFile.getName() + "】"); + } else if (ftpFile.getSize() == 0) { + getWrapper().setNewTask(true); + ALog.d(TAG, "FTP服务器上已存在该文件【" + ftpFile.getName() + "】,但文件长度为0,重新上传该文件"); + } else { + ALog.w(TAG, "FTP服务器已存在未完成的文件【" + + ftpFile.getName() + + ",size: " + + ftpFile.getSize() + + "】" + + "尝试从位置:" + + (ftpFile.getSize() - 1) + + "开始上传"); + getWrapper().setNewTask(false); + + // 修改记录 + ThreadRecord threadRecord = record.threadRecords.get(0); + //修改本地保存的停止地址为服务器上对应文件的大小 + threadRecord.startLocation = ftpFile.getSize() - 1; + } + } else { + ALog.d(TAG, "FTP服务器上不存在该文件"); + getWrapper().setNewTask(true); + ThreadRecord tr = record.threadRecords.get(0); + tr.startLocation = 0; + tr.endLocation = getFileSize(); + tr.isComplete = false; + } + } + + @Override + public ThreadRecord createThreadRecord(TaskRecord record, int threadId, long startL, long endL) { + ThreadRecord tr; + tr = new ThreadRecord(); + tr.taskKey = record.filePath; + tr.threadId = threadId; + tr.startLocation = startL; + tr.isComplete = false; + tr.threadType = getWrapper().getEntity().getTaskType(); + tr.endLocation = getFileSize(); + tr.blockLen = RecordUtil.getBlockLen(getFileSize(), threadId, record.threadNum); + return tr; + } + + @Override public TaskRecord createTaskRecord(int threadNum) { + TaskRecord record = new TaskRecord(); + record.fileName = getEntity().getFileName(); + record.filePath = getEntity().getFilePath(); + record.threadRecords = new ArrayList<>(); + record.threadNum = threadNum; + record.isBlock = false; + record.taskType = getWrapper().getEntity().getTaskType(); + record.isGroupRecord = getEntity().isGroupChild(); + + return record; + } + + @Override public int initTaskThreadNum() { + return 1; + } +} diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/NormalLoader.java b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/NormalLoader.java index 255beabc..3b9a3c57 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/loader/NormalLoader.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/loader/NormalLoader.java @@ -36,7 +36,7 @@ import java.io.File; */ public class NormalLoader extends AbsNormalLoader { private int startThreadNum; //启动的线程数 - private boolean isComplete = false; + protected boolean isComplete = false; private Looper looper; public NormalLoader(AbsTaskWrapper wrapper, IEventListener listener) { @@ -82,6 +82,10 @@ public class NormalLoader extends AbsNormalLoader { // } //} + protected Looper getLooper() { + return looper; + } + /** * 启动单线程任务 */ @@ -103,6 +107,7 @@ public class NormalLoader extends AbsNormalLoader { if (file.getParentFile() != null && !file.getParentFile().exists()) { FileUtil.createDir(file.getPath()); } + // 处理记录、初始化状态管理器 mRecord = mRecordHandler.getRecord(getFileSize()); mStateManager.setLooper(mRecord, looper); getTaskList().addAll(mTTBuilder.buildThreadTask(mRecord, @@ -116,6 +121,7 @@ public class NormalLoader extends AbsNormalLoader { getListener().onStart(mStateManager.getCurrentProgress()); } + // 启动线程任务 for (IThreadTask threadTask : getTaskList()) { ThreadTaskManager.getInstance().startThread(mTaskWrapper.getKey(), threadTask); }