parent
50b265f22a
commit
d217ebcb25
@ -0,0 +1,135 @@ |
||||
/* |
||||
* 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.common; |
||||
|
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.core.FtpUrlEntity; |
||||
import com.arialyy.aria.core.IdEntity; |
||||
import com.arialyy.aria.core.ProtocolType; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.ComponentUtil; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/9. |
||||
*/ |
||||
public class SFtpOption extends BaseOption { |
||||
|
||||
private String charSet, userName, password; |
||||
private boolean isNeedLogin = false; |
||||
private FtpUrlEntity urlEntity; |
||||
private String protocol; |
||||
private IdEntity idEntity = new IdEntity(); |
||||
|
||||
public SFtpOption() { |
||||
super(); |
||||
ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_M3U8); |
||||
} |
||||
|
||||
public SFtpOption charSet(String charSet) { |
||||
if (TextUtils.isEmpty(charSet)) { |
||||
throw new NullPointerException("字符编码为空"); |
||||
} |
||||
this.charSet = charSet; |
||||
return this; |
||||
} |
||||
|
||||
public SFtpOption login(String userName, String password) { |
||||
if (TextUtils.isEmpty(userName)) { |
||||
ALog.e(TAG, "用户名不能为null"); |
||||
return this; |
||||
} else if (TextUtils.isEmpty(password)) { |
||||
ALog.e(TAG, "密码不能为null"); |
||||
return this; |
||||
} |
||||
this.userName = userName; |
||||
this.password = password; |
||||
isNeedLogin = true; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* 设置协议类型 |
||||
* |
||||
* @param protocol {@link ProtocolType} |
||||
*/ |
||||
public SFtpOption setProtocol(String protocol) { |
||||
if (TextUtils.isEmpty(protocol)) { |
||||
ALog.e(TAG, "设置协议失败,协议信息为空"); |
||||
return this; |
||||
} |
||||
this.protocol = protocol; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* 设置私钥证书路径 |
||||
* |
||||
* @param prvKey 证书路径 |
||||
*/ |
||||
public SFtpOption setPrvKey(String prvKey) { |
||||
if (TextUtils.isEmpty(prvKey)) { |
||||
ALog.e(TAG, "设置私钥证书失败,证书内容为空"); |
||||
return this; |
||||
} |
||||
idEntity.prvKey = prvKey; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* 设置私钥密码 |
||||
* |
||||
* @param prvKeyPass 私钥密码 |
||||
*/ |
||||
public SFtpOption setPrvKeyPass(String prvKeyPass) { |
||||
if (TextUtils.isEmpty(prvKeyPass)) { |
||||
ALog.e(TAG, "设置证书密码失败,证书密码为空"); |
||||
return this; |
||||
} |
||||
idEntity.prvPass = prvKeyPass; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* 设置公钥证书 |
||||
* |
||||
* @param pubKey 公钥证书内容 |
||||
*/ |
||||
public SFtpOption setPubKey(String pubKey) { |
||||
if (TextUtils.isEmpty(pubKey)) { |
||||
ALog.e(TAG, "设置公钥失败,证书内容为空"); |
||||
return this; |
||||
} |
||||
idEntity.pubKey = pubKey; |
||||
return this; |
||||
} |
||||
|
||||
public SFtpOption setKnowHostPath(String knowHostPath) { |
||||
if (TextUtils.isEmpty(knowHostPath)) { |
||||
ALog.e(TAG, "knowhost 文件路径为空"); |
||||
return this; |
||||
} |
||||
idEntity.knowHost = knowHostPath; |
||||
return this; |
||||
} |
||||
|
||||
public void setUrlEntity(FtpUrlEntity urlEntity) { |
||||
this.urlEntity = urlEntity; |
||||
urlEntity.needLogin = isNeedLogin; |
||||
urlEntity.user = userName; |
||||
urlEntity.password = password; |
||||
urlEntity.idEntity = idEntity; |
||||
} |
||||
} |
@ -1,95 +0,0 @@ |
||||
///*
|
||||
// * 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.download;
|
||||
//
|
||||
//import com.arialyy.aria.core.TaskRecord;
|
||||
//import com.arialyy.aria.core.common.SubThreadConfig;
|
||||
//import com.arialyy.aria.core.listener.IEventListener;
|
||||
//import com.arialyy.aria.core.loader.NormalTTBuilder;
|
||||
//import com.arialyy.aria.core.loader.IRecordHandler;
|
||||
//import com.arialyy.aria.core.loader.IThreadTaskBuilder;
|
||||
//import com.arialyy.aria.core.loader.NormalLoader;
|
||||
//import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
|
||||
//import com.arialyy.aria.util.ALog;
|
||||
//import com.arialyy.aria.util.FileUtil;
|
||||
//import java.io.File;
|
||||
//import java.lang.reflect.InvocationHandler;
|
||||
//import java.lang.reflect.Method;
|
||||
//import java.lang.reflect.Proxy;
|
||||
//
|
||||
//final class FtpDLoader extends NormalLoader {
|
||||
// FtpDLoader(AbsTaskWrapper wrapper, IEventListener listener) {
|
||||
// super(wrapper, listener);
|
||||
// }
|
||||
//
|
||||
// @Override public void addComponent(IThreadTaskBuilder builder) {
|
||||
// mTTBuilder = (IThreadTaskBuilder) Proxy.newProxyInstance(getClass().getClassLoader(),
|
||||
// NormalTTBuilder.class.getInterfaces(), new InvocationHandler() {
|
||||
// NormalTTBuilder target = new NormalTTBuilder(mTaskWrapper);
|
||||
// @Override public Object invoke(Object proxy, Method method, Object[] args)
|
||||
// throws Exception {
|
||||
// if (method.getDeclaringClass() == Object.class) {
|
||||
// return method.invoke(this, args);
|
||||
// }
|
||||
//
|
||||
// //if (method.isDefault()) {
|
||||
// // Constructor<MethodHandles.Lookup>
|
||||
// // constructor =
|
||||
// // MethodHandles.Lookup.class.getDeclaredConstructor(Class.class, int.class);
|
||||
// // constructor.setAccessible(true);
|
||||
// // return constructor.newInstance(AbsNormalTTBuilder.class, -1 /* trusted */)
|
||||
// // .unreflectSpecial(method, AbsNormalTTBuilder.class)
|
||||
// // .bindTo(proxy)
|
||||
// // .invokeWithArguments(args);
|
||||
// //}
|
||||
//
|
||||
// String methodName = method.getName();
|
||||
// switch (methodName) {
|
||||
//
|
||||
// case "handleNewTask":
|
||||
// return handleNewTask((TaskRecord) args[0], (int) args[1]);
|
||||
// case "getAdapter":
|
||||
// return new FtpDThreadTaskAdapter((SubThreadConfig) args[0]);
|
||||
// }
|
||||
//
|
||||
// return method.invoke(target, args);
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 处理新任务
|
||||
// */
|
||||
// private boolean handleNewTask(TaskRecord record, int totalThreadNum) {
|
||||
// File temp = new File(getEntity().getFilePath());
|
||||
// if (!record.isBlock) {
|
||||
// if (temp.exists()) {
|
||||
// FileUtil.deleteFile(temp);
|
||||
// }
|
||||
// //CommonUtil.createFile(mTempFile.getPath());
|
||||
// } else {
|
||||
// for (int i = 0; i < totalThreadNum; i++) {
|
||||
// File blockFile =
|
||||
// new File(String.format(IRecordHandler.SUB_PATH, temp.getPath(), i));
|
||||
// if (blockFile.exists()) {
|
||||
// ALog.d(TAG, String.format("分块【%s】已经存在,将删除该分块", i));
|
||||
// FileUtil.deleteFile(blockFile);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
// }
|
||||
//}
|
@ -0,0 +1,11 @@ |
||||
apply plugin: 'com.novoda.bintray-release' |
||||
publish { |
||||
artifactId = 'sftpComponent' |
||||
uploadName = 'SFTPComponent' |
||||
userOrg = rootProject.ext.userOrg |
||||
groupId = rootProject.ext.groupId |
||||
publishVersion = rootProject.ext.publishVersion |
||||
desc = rootProject.ext.desc |
||||
website = rootProject.ext.website |
||||
licences = rootProject.ext.licences |
||||
} |
@ -0,0 +1,92 @@ |
||||
/* |
||||
* 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.sftp.download; |
||||
|
||||
import com.arialyy.aria.core.TaskRecord; |
||||
import com.arialyy.aria.core.ThreadRecord; |
||||
import com.arialyy.aria.core.common.RecordHandler; |
||||
import com.arialyy.aria.core.common.RecordHelper; |
||||
import com.arialyy.aria.core.config.Configuration; |
||||
import com.arialyy.aria.core.download.DTaskWrapper; |
||||
import com.arialyy.aria.core.loader.IRecordHandler; |
||||
import com.arialyy.aria.core.wrapper.ITaskWrapper; |
||||
import com.arialyy.aria.util.RecordUtil; |
||||
import java.util.ArrayList; |
||||
|
||||
/** |
||||
* @Author lyy |
||||
* @Date 2019-09-19 |
||||
*/ |
||||
final class SFtpDRecordHandler extends RecordHandler { |
||||
|
||||
SFtpDRecordHandler(DTaskWrapper wrapper) { |
||||
super(wrapper); |
||||
} |
||||
|
||||
@Override public void handlerTaskRecord(TaskRecord record) { |
||||
RecordHelper helper = new RecordHelper(getWrapper(), record); |
||||
if (record.threadNum == 1) { |
||||
helper.handleSingleThreadRecord(); |
||||
} else { |
||||
if (getWrapper().isSupportBP()) { |
||||
if (record.isBlock) { |
||||
helper.handleBlockRecord(); |
||||
} else { |
||||
helper.handleMultiRecord(); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
@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 = record.taskType; |
||||
//最后一个线程的结束位置即为文件的总长度
|
||||
if (threadId == (record.threadNum - 1)) { |
||||
endL = getFileSize(); |
||||
} |
||||
tr.endLocation = endL; |
||||
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 = threadNum > 1; |
||||
record.taskType = ITaskWrapper.D_SFTP; |
||||
record.isGroupRecord = false; |
||||
|
||||
return record; |
||||
} |
||||
|
||||
@Override public int initTaskThreadNum() { |
||||
int threadNum = Configuration.getInstance().downloadCfg.getThreadNum(); |
||||
return getFileSize() <= IRecordHandler.SUB_LEN |
||||
|| threadNum == 1 |
||||
? 1 |
||||
: threadNum; |
||||
} |
||||
} |
@ -0,0 +1,69 @@ |
||||
/* |
||||
* 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.sftp.upload; |
||||
|
||||
import com.arialyy.aria.core.common.CompleteInfo; |
||||
import com.arialyy.aria.core.upload.UTaskWrapper; |
||||
import com.arialyy.aria.core.upload.UploadEntity; |
||||
import com.arialyy.aria.sftp.AbsSFtpInfoTask; |
||||
import com.arialyy.aria.sftp.SFtpTaskOption; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import com.jcraft.jsch.ChannelSftp; |
||||
import com.jcraft.jsch.JSchException; |
||||
import com.jcraft.jsch.Session; |
||||
import com.jcraft.jsch.SftpATTRS; |
||||
import com.jcraft.jsch.SftpException; |
||||
import java.io.UnsupportedEncodingException; |
||||
|
||||
final class SFtpUInfoTask extends AbsSFtpInfoTask<UTaskWrapper> { |
||||
static final int ISCOMPLETE = 0xa1; |
||||
|
||||
SFtpUInfoTask(UTaskWrapper uTaskWrapper) { |
||||
super(uTaskWrapper); |
||||
} |
||||
|
||||
@Override protected void getFileInfo(Session session) |
||||
throws JSchException, UnsupportedEncodingException, SftpException { |
||||
SFtpTaskOption option = (SFtpTaskOption) getWrapper().getTaskOption(); |
||||
ChannelSftp channel = (ChannelSftp) session.openChannel("sftp"); |
||||
channel.connect(1000); |
||||
|
||||
String remotePath = option.getUrlEntity().remotePath; |
||||
String temp = CommonUtil.convertSFtpChar(getOption().getCharSet(), remotePath) |
||||
+ "/" |
||||
+ getWrapper().getEntity().getFileName(); |
||||
|
||||
SftpATTRS attr = null; |
||||
try { |
||||
attr = channel.stat(temp); |
||||
} catch (Exception e) { |
||||
ALog.d(TAG, String.format("文件不存在,remotePath:%s", remotePath)); |
||||
} |
||||
|
||||
boolean isComplete = false; |
||||
UploadEntity entity = getWrapper().getEntity(); |
||||
if (attr != null && attr.getSize() == entity.getFileSize()) { |
||||
isComplete = true; |
||||
} |
||||
|
||||
CompleteInfo info = new CompleteInfo(); |
||||
info.code = isComplete ? ISCOMPLETE : 200; |
||||
info.obj = attr; |
||||
channel.disconnect(); |
||||
callback.onSucceed(getWrapper().getKey(), info); |
||||
} |
||||
} |
@ -0,0 +1,155 @@ |
||||
/* |
||||
* 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.sftp.upload; |
||||
|
||||
import android.os.Handler; |
||||
import android.os.Looper; |
||||
import com.arialyy.aria.core.common.AbsEntity; |
||||
import com.arialyy.aria.core.common.CompleteInfo; |
||||
import com.arialyy.aria.core.event.EventMsgUtil; |
||||
import com.arialyy.aria.core.inf.IThreadStateManager; |
||||
import com.arialyy.aria.core.listener.IDLoadListener; |
||||
import com.arialyy.aria.core.listener.IEventListener; |
||||
import com.arialyy.aria.core.loader.AbsNormalLoader; |
||||
import com.arialyy.aria.core.loader.IInfoTask; |
||||
import com.arialyy.aria.core.loader.IRecordHandler; |
||||
import com.arialyy.aria.core.loader.IThreadTaskBuilder; |
||||
import com.arialyy.aria.core.manager.ThreadTaskManager; |
||||
import com.arialyy.aria.core.task.IThreadTask; |
||||
import com.arialyy.aria.core.upload.UTaskWrapper; |
||||
import com.arialyy.aria.core.upload.UploadEntity; |
||||
import com.arialyy.aria.exception.BaseException; |
||||
import com.arialyy.aria.util.FileUtil; |
||||
import com.jcraft.jsch.SftpATTRS; |
||||
import java.io.File; |
||||
|
||||
final class SFtpULoader extends AbsNormalLoader<UTaskWrapper> { |
||||
|
||||
private Looper looper; |
||||
|
||||
SFtpULoader(UTaskWrapper wrapper, IEventListener listener) { |
||||
super(wrapper, listener); |
||||
mTempFile = new File(getEntity().getFilePath()); |
||||
EventMsgUtil.getDefault().register(this); |
||||
setUpdateInterval(wrapper.getConfig().getUpdateInterval()); |
||||
} |
||||
|
||||
private UploadEntity getEntity() { |
||||
return mTaskWrapper.getEntity(); |
||||
} |
||||
|
||||
@Override public long getFileSize() { |
||||
return getEntity().getFileSize(); |
||||
} |
||||
|
||||
/** |
||||
* 设置最大下载/上传速度AbsFtpInfoThread |
||||
* |
||||
* @param maxSpeed 单位为:kb |
||||
*/ |
||||
protected void setMaxSpeed(int maxSpeed) { |
||||
for (IThreadTask threadTask : getTaskList()) { |
||||
if (threadTask != null) { |
||||
threadTask.setMaxSpeed(maxSpeed); |
||||
} |
||||
} |
||||
} |
||||
|
||||
@Override public void onDestroy() { |
||||
super.onDestroy(); |
||||
EventMsgUtil.getDefault().unRegister(this); |
||||
} |
||||
|
||||
/** |
||||
* 启动单线程任务 |
||||
*/ |
||||
@Override |
||||
public void handleTask(Looper looper) { |
||||
if (isBreak()) { |
||||
return; |
||||
} |
||||
this.looper = looper; |
||||
mInfoTask.run(); |
||||
} |
||||
|
||||
private void startThreadTask(SftpATTRS attrs) { |
||||
|
||||
if (getListener() instanceof IDLoadListener) { |
||||
((IDLoadListener) getListener()).onPostPre(getEntity().getFileSize()); |
||||
} |
||||
File file = new File(getEntity().getFilePath()); |
||||
if (file.getParentFile() != null && !file.getParentFile().exists()) { |
||||
FileUtil.createDir(file.getPath()); |
||||
} |
||||
// 处理记录、初始化状态管理器
|
||||
SFtpURecordHandler recordHandler = (SFtpURecordHandler) mRecordHandler; |
||||
recordHandler.setFtpAttrs(attrs); |
||||
mRecord = recordHandler.getRecord(getFileSize()); |
||||
mStateManager.setLooper(mRecord, looper); |
||||
|
||||
// 创建线程任务
|
||||
getTaskList().addAll(mTTBuilder.buildThreadTask(mRecord, |
||||
new Handler(looper, 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); |
||||
} |
||||
|
||||
// 启动定时器
|
||||
startTimer(); |
||||
} |
||||
|
||||
@Override public long getCurrentProgress() { |
||||
return isRunning() ? mStateManager.getCurrentProgress() : getEntity().getCurrentProgress(); |
||||
} |
||||
|
||||
@Override public void addComponent(IRecordHandler recordHandler) { |
||||
mRecordHandler = recordHandler; |
||||
} |
||||
|
||||
@Override public void addComponent(IInfoTask infoTask) { |
||||
mInfoTask = infoTask; |
||||
infoTask.setCallback(new IInfoTask.Callback() { |
||||
@Override public void onSucceed(String key, CompleteInfo info) { |
||||
if (info.code == SFtpUInfoTask.ISCOMPLETE) { |
||||
getListener().onComplete(); |
||||
} else { |
||||
startThreadTask((SftpATTRS) info.obj); |
||||
} |
||||
} |
||||
|
||||
@Override public void onFail(AbsEntity entity, BaseException e, boolean needRetry) { |
||||
getListener().onFail(needRetry, e); |
||||
} |
||||
}); |
||||
} |
||||
|
||||
@Override public void addComponent(IThreadStateManager threadState) { |
||||
mStateManager = threadState; |
||||
} |
||||
|
||||
@Override public void addComponent(IThreadTaskBuilder builder) { |
||||
mTTBuilder = builder; |
||||
} |
||||
} |
@ -0,0 +1,55 @@ |
||||
/* |
||||
* 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.sftp.upload; |
||||
|
||||
import com.arialyy.aria.core.listener.IEventListener; |
||||
import com.arialyy.aria.core.loader.AbsNormalLoader; |
||||
import com.arialyy.aria.core.loader.AbsNormalLoaderUtil; |
||||
import com.arialyy.aria.core.loader.LoaderStructure; |
||||
import com.arialyy.aria.core.loader.NormalTTBuilder; |
||||
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.sftp.SFtpTaskOption; |
||||
|
||||
/** |
||||
* sftp下载工具 |
||||
* |
||||
* @author lyy |
||||
*/ |
||||
public class SFtpULoaderUtil extends AbsNormalLoaderUtil { |
||||
|
||||
public SFtpULoaderUtil(AbsTaskWrapper wrapper, IEventListener listener) { |
||||
super(wrapper, listener); |
||||
wrapper.generateTaskOption(SFtpTaskOption.class); |
||||
} |
||||
|
||||
@Override public AbsNormalLoader getLoader() { |
||||
return mLoader == null ? new SFtpULoader((UTaskWrapper) getTaskWrapper(), getListener()) |
||||
: mLoader; |
||||
} |
||||
|
||||
@Override public LoaderStructure BuildLoaderStructure() { |
||||
LoaderStructure structure = new LoaderStructure(); |
||||
structure.addComponent(new SFtpURecordHandler((UTaskWrapper) getTaskWrapper())) |
||||
.addComponent(new NormalThreadStateManager(getListener())) |
||||
.addComponent(new SFtpUInfoTask((UTaskWrapper) getTaskWrapper())) |
||||
.addComponent(new NormalTTBuilder(getTaskWrapper(), new SFtpUTTBuilderAdapter( |
||||
(UTaskWrapper) getTaskWrapper()))); |
||||
structure.accept(getLoader()); |
||||
return structure; |
||||
} |
||||
} |
@ -0,0 +1,115 @@ |
||||
/* |
||||
* 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.sftp.upload; |
||||
|
||||
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.core.upload.UploadEntity; |
||||
import com.arialyy.aria.core.wrapper.ITaskWrapper; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.RecordUtil; |
||||
import com.jcraft.jsch.SftpATTRS; |
||||
import java.util.ArrayList; |
||||
|
||||
/** |
||||
* 上传任务记录处理器 |
||||
*/ |
||||
final class SFtpURecordHandler extends RecordHandler { |
||||
private SftpATTRS ftpAttrs; |
||||
|
||||
SFtpURecordHandler(UTaskWrapper wrapper) { |
||||
super(wrapper); |
||||
} |
||||
|
||||
void setFtpAttrs(SftpATTRS ftpAttrs) { |
||||
this.ftpAttrs = ftpAttrs; |
||||
} |
||||
|
||||
@Override public void handlerTaskRecord(TaskRecord record) { |
||||
if (record.threadRecords == null || record.threadRecords.isEmpty()) { |
||||
record.threadRecords = new ArrayList<>(); |
||||
record.threadRecords.add( |
||||
createThreadRecord(record, 0, ftpAttrs == null ? 0 : ftpAttrs.getSize(), getFileSize())); |
||||
} |
||||
|
||||
if (ftpAttrs != null) { |
||||
UploadEntity entity = (UploadEntity) getWrapper().getEntity(); |
||||
//远程文件已完成
|
||||
if (ftpAttrs.getSize() == getFileSize()) { |
||||
record.threadRecords.get(0).isComplete = true; |
||||
ALog.d(TAG, "FTP服务器上已存在该文件【" + entity.getFileName() + "】"); |
||||
} else if (ftpAttrs.getSize() == 0) { |
||||
getWrapper().setNewTask(true); |
||||
ALog.d(TAG, "FTP服务器上已存在该文件【" + entity.getFileName() + "】,但文件长度为0,重新上传该文件"); |
||||
} else { |
||||
ALog.w(TAG, "FTP服务器已存在未完成的文件【" |
||||
+ entity.getFileName() |
||||
+ ",size: " |
||||
+ ftpAttrs.getSize() |
||||
+ "】" |
||||
+ "尝试从位置:" |
||||
+ (ftpAttrs.getSize() - 1) |
||||
+ "开始上传"); |
||||
getWrapper().setNewTask(false); |
||||
|
||||
// 修改记录
|
||||
ThreadRecord threadRecord = record.threadRecords.get(0); |
||||
//修改本地保存的停止地址为服务器上对应文件的大小
|
||||
threadRecord.startLocation = ftpAttrs.getSize() - 1; |
||||
} |
||||
} else { |
||||
ALog.d(TAG, "SFTP服务器上不存在该文件"); |
||||
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 = record.taskType; |
||||
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 = ITaskWrapper.U_SFTP; |
||||
record.isGroupRecord = getEntity().isGroupChild(); |
||||
|
||||
return record; |
||||
} |
||||
|
||||
@Override public int initTaskThreadNum() { |
||||
return 1; |
||||
} |
||||
} |
@ -0,0 +1,73 @@ |
||||
/* |
||||
* 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.sftp.upload; |
||||
|
||||
import android.os.Handler; |
||||
import com.arialyy.aria.core.FtpUrlEntity; |
||||
import com.arialyy.aria.core.TaskRecord; |
||||
import com.arialyy.aria.core.ThreadRecord; |
||||
import com.arialyy.aria.core.common.SubThreadConfig; |
||||
import com.arialyy.aria.core.loader.AbsNormalTTBuilderAdapter; |
||||
import com.arialyy.aria.core.task.IThreadTaskAdapter; |
||||
import com.arialyy.aria.core.upload.UTaskWrapper; |
||||
import com.arialyy.aria.sftp.SFtpSessionManager; |
||||
import com.arialyy.aria.sftp.SFtpTaskOption; |
||||
import com.arialyy.aria.sftp.SFtpUtil; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import com.jcraft.jsch.JSchException; |
||||
import com.jcraft.jsch.Session; |
||||
import java.io.UnsupportedEncodingException; |
||||
|
||||
final class SFtpUTTBuilderAdapter extends AbsNormalTTBuilderAdapter { |
||||
private SFtpTaskOption option; |
||||
|
||||
SFtpUTTBuilderAdapter(UTaskWrapper wrapper) { |
||||
option = (SFtpTaskOption) wrapper.getTaskOption(); |
||||
} |
||||
|
||||
@Override public IThreadTaskAdapter getAdapter(SubThreadConfig config) { |
||||
return new SFtpUThreadTaskAdapter(config); |
||||
} |
||||
|
||||
@Override |
||||
protected SubThreadConfig getSubThreadConfig(Handler stateHandler, ThreadRecord threadRecord, |
||||
boolean isBlock, int startNum) { |
||||
SubThreadConfig config = |
||||
super.getSubThreadConfig(stateHandler, threadRecord, isBlock, startNum); |
||||
|
||||
FtpUrlEntity entity = option.getUrlEntity(); |
||||
String key = |
||||
CommonUtil.getStrMd5(entity.hostName + entity.port + entity.user + threadRecord.threadId); |
||||
Session session = SFtpSessionManager.getInstance().getSession(key); |
||||
if (session == null) { |
||||
try { |
||||
session = SFtpUtil.getInstance().getSession(entity, threadRecord.threadId); |
||||
} catch (JSchException e) { |
||||
e.printStackTrace(); |
||||
} catch (UnsupportedEncodingException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
config.obj = session; |
||||
|
||||
return config; |
||||
} |
||||
|
||||
@Override public boolean handleNewTask(TaskRecord record, int totalThreadNum) { |
||||
|
||||
return true; |
||||
} |
||||
} |
@ -0,0 +1,201 @@ |
||||
/* |
||||
* 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.sftp.upload; |
||||
|
||||
import com.arialyy.aria.core.common.SubThreadConfig; |
||||
import com.arialyy.aria.core.task.AbsThreadTaskAdapter; |
||||
import com.arialyy.aria.core.upload.UploadEntity; |
||||
import com.arialyy.aria.exception.AriaException; |
||||
import com.arialyy.aria.sftp.SFtpTaskOption; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.BufferedRandomAccessFile; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import com.jcraft.jsch.ChannelSftp; |
||||
import com.jcraft.jsch.JSchException; |
||||
import com.jcraft.jsch.Session; |
||||
import com.jcraft.jsch.SftpException; |
||||
import com.jcraft.jsch.SftpProgressMonitor; |
||||
import java.io.IOException; |
||||
import java.io.OutputStream; |
||||
import java.io.UnsupportedEncodingException; |
||||
|
||||
/** |
||||
* sftp 线程任务适配器 |
||||
* |
||||
* @author lyy |
||||
*/ |
||||
final class SFtpUThreadTaskAdapter extends AbsThreadTaskAdapter { |
||||
private ChannelSftp channelSftp; |
||||
private Session session; |
||||
private SFtpTaskOption option; |
||||
|
||||
SFtpUThreadTaskAdapter(SubThreadConfig config) { |
||||
super(config); |
||||
session = (Session) config.obj; |
||||
option = (SFtpTaskOption) getTaskWrapper().getTaskOption(); |
||||
} |
||||
|
||||
@Override protected void handlerThreadTask() { |
||||
if (session == null) { |
||||
fail(new AriaException(TAG, "session 为空"), false); |
||||
return; |
||||
} |
||||
try { |
||||
ALog.d(TAG, |
||||
String.format("任务【%s】线程__%s__开始上传【开始位置 : %s,结束位置:%s】", getTaskWrapper().getKey(), |
||||
getThreadRecord().threadId, getThreadRecord().startLocation, |
||||
getThreadRecord().endLocation)); |
||||
int timeout = getTaskConfig().getConnectTimeOut(); |
||||
if (!session.isConnected()) { |
||||
session.connect(timeout); |
||||
} |
||||
// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码
|
||||
String charSet = option.getCharSet(); |
||||
String remotePath = |
||||
CommonUtil.convertSFtpChar(charSet, option.getUrlEntity().remotePath); |
||||
channelSftp = (ChannelSftp) session.openChannel("sftp"); |
||||
channelSftp.connect(timeout); |
||||
|
||||
if (!dirIsExist(remotePath)) { |
||||
createDir(remotePath); |
||||
} |
||||
channelSftp.cd(remotePath); |
||||
upload(remotePath); |
||||
} catch (JSchException e) { |
||||
e.printStackTrace(); |
||||
fail(null, false); |
||||
} catch (UnsupportedEncodingException e) { |
||||
e.printStackTrace(); |
||||
fail(null, false); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
fail(null, true); |
||||
} catch (SftpException e) { |
||||
e.printStackTrace(); |
||||
fail(null, false); |
||||
ALog.d(TAG, "错误类型:" + e.id); |
||||
} finally { |
||||
channelSftp.disconnect(); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 远程文件夹是否存在 |
||||
* |
||||
* @return true 文件夹存在 |
||||
*/ |
||||
private boolean dirIsExist(String remotePath) { |
||||
try { |
||||
channelSftp.ls(remotePath); |
||||
} catch (SftpException e) { |
||||
return false; |
||||
} |
||||
return true; |
||||
} |
||||
|
||||
/** |
||||
* 创建文件夹 |
||||
* |
||||
* @throws SftpException |
||||
*/ |
||||
private void createDir(String remotePath) throws SftpException { |
||||
String[] folders = remotePath.split("/"); |
||||
|
||||
for (String folder : folders) { |
||||
if (folder.length() > 0) { |
||||
try { |
||||
channelSftp.cd(folder); |
||||
} catch (SftpException e) { |
||||
channelSftp.mkdir(folder); |
||||
channelSftp.cd(folder); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 恢复上传 |
||||
* |
||||
* @throws SftpException |
||||
* @throws IOException |
||||
*/ |
||||
private void upload(String remotePath) throws SftpException, IOException { |
||||
UploadEntity entity = (UploadEntity) getTaskWrapper().getEntity(); |
||||
remotePath = remotePath.concat("/").concat(entity.getFileName()); |
||||
BufferedRandomAccessFile brf = new BufferedRandomAccessFile(getThreadConfig().tempFile, "r"); |
||||
int mode = ChannelSftp.OVERWRITE; |
||||
boolean isResume = false; |
||||
if (getThreadRecord().startLocation > 0) { |
||||
brf.seek(getThreadRecord().startLocation); |
||||
mode = ChannelSftp.APPEND; |
||||
isResume = true; |
||||
} |
||||
OutputStream os = channelSftp.put(remotePath, new Monitor(isResume), mode); |
||||
byte[] buffer = new byte[4096]; |
||||
int bytesRead; |
||||
while ((bytesRead = brf.read(buffer)) != -1) { |
||||
if (getThreadTask().isBreak()) { |
||||
break; |
||||
} |
||||
os.write(buffer, 0, bytesRead); |
||||
if (mSpeedBandUtil != null) { |
||||
mSpeedBandUtil.limitNextBytes(bytesRead); |
||||
} |
||||
} |
||||
os.flush(); |
||||
os.close(); |
||||
brf.close(); |
||||
} |
||||
|
||||
private class Monitor implements SftpProgressMonitor { |
||||
|
||||
private boolean isResume; |
||||
|
||||
private Monitor(boolean isResume) { |
||||
this.isResume = isResume; |
||||
} |
||||
|
||||
@Override public void init(int op, String src, String dest, long max) { |
||||
ALog.d(TAG, String.format("op = %s; src = %s; dest = %s; max = %s", op, src, dest, max)); |
||||
} |
||||
|
||||
/** |
||||
* @param count 已传输的数据 |
||||
* @return false 取消任务 |
||||
*/ |
||||
@Override public boolean count(long count) { |
||||
|
||||
/* |
||||
* jsch 如果是恢复任务,第一次回调count会将已下载的长度返回,后面才是新增的文件长度。 |
||||
* 所以恢复任务的话,需要忽略一次回调 |
||||
*/ |
||||
if (!isResume) { |
||||
progress(count); |
||||
} |
||||
isResume = false; |
||||
|
||||
return !getThreadTask().isBreak(); |
||||
} |
||||
|
||||
@Override public void end() { |
||||
if (getThreadTask().isBreak()) { |
||||
return; |
||||
} |
||||
|
||||
complete(); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,239 @@ |
||||
/* |
||||
* 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.simple.core.upload; |
||||
|
||||
import android.content.Intent; |
||||
import android.net.Uri; |
||||
import android.os.Bundle; |
||||
import android.os.Environment; |
||||
import android.util.Log; |
||||
import android.view.View; |
||||
import androidx.annotation.Nullable; |
||||
import androidx.lifecycle.Observer; |
||||
import androidx.lifecycle.ViewModelProviders; |
||||
import com.arialyy.annotations.Upload; |
||||
import com.arialyy.aria.core.Aria; |
||||
import com.arialyy.aria.core.common.SFtpOption; |
||||
import com.arialyy.aria.core.inf.IEntity; |
||||
import com.arialyy.aria.core.task.UploadTask; |
||||
import com.arialyy.aria.core.upload.UploadEntity; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import com.arialyy.frame.util.FileUtil; |
||||
import com.arialyy.frame.util.show.T; |
||||
import com.arialyy.simple.R; |
||||
import com.arialyy.simple.base.BaseActivity; |
||||
import com.arialyy.simple.common.ModifyUrlDialog; |
||||
import com.arialyy.simple.databinding.ActivitySftpUploadBinding; |
||||
import com.arialyy.simple.util.AppUtil; |
||||
import java.io.File; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
/** |
||||
* Created by lyy on 2017/7/28. Ftp 文件上传demo |
||||
*/ |
||||
public class SFtpUploadActivity extends BaseActivity<ActivitySftpUploadBinding> { |
||||
private final int OPEN_FILE_MANAGER_CODE = 0xB1; |
||||
private String mFilePath; |
||||
private String mUrl; |
||||
private UploadModule mModule; |
||||
private long mTaskId = -1; |
||||
private String user = "tester", pwd = "password"; |
||||
|
||||
@Override protected void init(Bundle savedInstanceState) { |
||||
setTile("D_FTP 文件上传"); |
||||
super.init(savedInstanceState); |
||||
Aria.upload(this).register(); |
||||
|
||||
getBinding().setViewModel(this); |
||||
setUI(); |
||||
} |
||||
|
||||
private void setUI() { |
||||
mModule = ViewModelProviders.of(this).get(UploadModule.class); |
||||
mModule.getSFtpInfo(this).observe(this, new Observer<UploadEntity>() { |
||||
@Override public void onChanged(@Nullable UploadEntity entity) { |
||||
if (entity != null) { |
||||
mTaskId = entity.getId(); |
||||
if (entity.getFileSize() != 0) { |
||||
getBinding().setFileSize(CommonUtil.formatFileSize(entity.getFileSize())); |
||||
getBinding().setProgress(entity.isComplete() ? 100 |
||||
: (int) (entity.getCurrentProgress() * 100 / entity.getFileSize())); |
||||
} |
||||
getBinding().setUrl(entity.getUrl()); |
||||
getBinding().setFilePath(entity.getFilePath()); |
||||
mUrl = entity.getUrl(); |
||||
mFilePath = entity.getFilePath(); |
||||
getBinding().setStateStr(getString( |
||||
entity.getState() == IEntity.STATE_RUNNING ? R.string.stop : R.string.start)); |
||||
} else { |
||||
getBinding().setStateStr(getString(R.string.resume)); |
||||
} |
||||
} |
||||
}); |
||||
setHelpCode(); |
||||
} |
||||
|
||||
private void setHelpCode() { |
||||
//try {
|
||||
// getBinding().codeView.setSource(AppUtil.getHelpCode(this, "FtpUpload.java"));
|
||||
//} catch (IOException e) {
|
||||
// e.printStackTrace();
|
||||
//}
|
||||
} |
||||
|
||||
@Override protected int setLayoutId() { |
||||
return R.layout.activity_sftp_upload; |
||||
} |
||||
|
||||
public void chooseUrl() { |
||||
ModifyUrlDialog dialog = |
||||
new ModifyUrlDialog(this, getString(R.string.modify_url_dialog_title), mUrl); |
||||
dialog.show(getSupportFragmentManager(), "ModifyUrlDialog"); |
||||
} |
||||
|
||||
public void chooseFilePath() { |
||||
AppUtil.chooseFile(this, new File(mFilePath), null, OPEN_FILE_MANAGER_CODE); |
||||
} |
||||
|
||||
public void onClick(View view) { |
||||
switch (view.getId()) { |
||||
case R.id.start: |
||||
if (mTaskId == -1) { |
||||
mTaskId = Aria.upload(this) |
||||
.loadFtp(mFilePath) |
||||
.setUploadUrl(mUrl) |
||||
.sftpOption(getOption()) |
||||
.ignoreFilePathOccupy() |
||||
.create(); |
||||
getBinding().setStateStr(getString(R.string.stop)); |
||||
break; |
||||
} |
||||
if (Aria.upload(this).loadFtp(mTaskId).isRunning()) { |
||||
Aria.upload(this).loadFtp(mTaskId).stop(); |
||||
getBinding().setStateStr(getString(R.string.resume)); |
||||
} else { |
||||
Aria.upload(this) |
||||
.loadFtp(mTaskId) |
||||
.sftpOption(getOption()) |
||||
.resume(); |
||||
getBinding().setStateStr(getString(R.string.stop)); |
||||
} |
||||
//upload();
|
||||
break; |
||||
case R.id.cancel: |
||||
Aria.upload(this).loadFtp(mTaskId).cancel(false); |
||||
mTaskId = -1; |
||||
getBinding().setStateStr(getString(R.string.start)); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
private void upload() { |
||||
List<String> paths = new ArrayList<>(); |
||||
paths.add(Environment.getExternalStorageDirectory().getPath() + "/Download/img/img/1.jpg"); |
||||
paths.add(Environment.getExternalStorageDirectory().getPath() + "/Download/img/img/2.jpg"); |
||||
paths.add(Environment.getExternalStorageDirectory().getPath() + "/Download/img/img/3.jpg"); |
||||
paths.add(Environment.getExternalStorageDirectory().getPath() + "/Download/img/img/4.jpg"); |
||||
paths.add(Environment.getExternalStorageDirectory().getPath() + "/Download/img/img/5.jpg"); |
||||
paths.add(Environment.getExternalStorageDirectory().getPath() + "/Download/img/img/6.jpg"); |
||||
paths.add(Environment.getExternalStorageDirectory().getPath() + "/Download/img/img/7.jpg"); |
||||
paths.add(Environment.getExternalStorageDirectory().getPath() + "/Download/img/img/8.jpg"); |
||||
paths.add(Environment.getExternalStorageDirectory().getPath() + "/Download/img/img/9.jpg"); |
||||
paths.add(Environment.getExternalStorageDirectory().getPath() + "/Download/img/img/10.jpg"); |
||||
for (String path : paths) { |
||||
Aria.upload(this) |
||||
.loadFtp(path) |
||||
.setUploadUrl(mUrl) |
||||
.sftpOption(getOption()) |
||||
.ignoreFilePathOccupy() |
||||
.create(); |
||||
} |
||||
} |
||||
|
||||
private SFtpOption getOption() { |
||||
SFtpOption option = new SFtpOption(); |
||||
option.login(user, pwd); |
||||
return option; |
||||
} |
||||
|
||||
@Upload.onWait void onWait(UploadTask task) { |
||||
Log.d(TAG, task.getTaskName() + "_wait"); |
||||
} |
||||
|
||||
@Upload.onPre public void onPre(UploadTask task) { |
||||
getBinding().setFileSize(task.getConvertFileSize()); |
||||
} |
||||
|
||||
@Upload.onTaskStart public void taskStart(UploadTask task) { |
||||
Log.d(TAG, "开始上传,md5:" + FileUtil.getFileMD5(new File(task.getEntity().getFilePath()))); |
||||
} |
||||
|
||||
@Upload.onTaskResume public void taskResume(UploadTask task) { |
||||
Log.d(TAG, "恢复上传"); |
||||
} |
||||
|
||||
@Upload.onTaskStop public void taskStop(UploadTask task) { |
||||
getBinding().setSpeed(""); |
||||
Log.d(TAG, "停止上传"); |
||||
} |
||||
|
||||
@Upload.onTaskCancel public void taskCancel(UploadTask task) { |
||||
getBinding().setSpeed(""); |
||||
getBinding().setFileSize(""); |
||||
getBinding().setProgress(0); |
||||
Log.d(TAG, "删除任务"); |
||||
} |
||||
|
||||
@Upload.onTaskFail public void taskFail(UploadTask task) { |
||||
Log.d(TAG, "上传失败"); |
||||
getBinding().setStateStr(getString(R.string.resume)); |
||||
} |
||||
|
||||
@Upload.onTaskRunning public void taskRunning(UploadTask task) { |
||||
Log.d(TAG, "PP = " + task.getPercent()); |
||||
getBinding().setProgress(task.getPercent()); |
||||
getBinding().setSpeed(task.getConvertSpeed()); |
||||
} |
||||
|
||||
@Upload.onTaskComplete public void taskComplete(UploadTask task) { |
||||
getBinding().setProgress(100); |
||||
getBinding().setSpeed(""); |
||||
T.showShort(this, "文件:" + task.getEntity().getFileName() + ",上传完成"); |
||||
getBinding().setStateStr(getString(R.string.re_start)); |
||||
} |
||||
|
||||
@Override protected void dataCallback(int result, Object data) { |
||||
super.dataCallback(result, data); |
||||
if (result == ModifyUrlDialog.MODIFY_URL_DIALOG_RESULT) { |
||||
mModule.updateFtpUrl(this, String.valueOf(data)); |
||||
} |
||||
} |
||||
|
||||
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { |
||||
super.onActivityResult(requestCode, resultCode, data); |
||||
if (requestCode == OPEN_FILE_MANAGER_CODE && resultCode == RESULT_OK) { |
||||
Uri uri = data.getData(); |
||||
if (uri != null) { |
||||
mModule.updateFtpFilePath(this, uri.getPath()); |
||||
ALog.d(TAG, String.format("选择的文件路径:%s", uri.getPath())); |
||||
} else { |
||||
ALog.d(TAG, "没有选择文件"); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,83 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android" |
||||
xmlns:bind="http://schemas.android.com/apk/res-auto" |
||||
> |
||||
<data> |
||||
<variable |
||||
name="fileSize" |
||||
type="String" |
||||
/> |
||||
<variable |
||||
name="speed" |
||||
type="String" |
||||
/> |
||||
<variable |
||||
name="progress" |
||||
type="int" |
||||
/> |
||||
<variable |
||||
name="url" |
||||
type="String" |
||||
/> |
||||
<variable |
||||
name="filePath" |
||||
type="String" |
||||
/> |
||||
<variable |
||||
name="viewModel" |
||||
type="com.arialyy.simple.core.upload.SFtpUploadActivity" |
||||
/> |
||||
<variable |
||||
name="stateStr" |
||||
type="String" |
||||
/> |
||||
</data> |
||||
|
||||
<LinearLayout |
||||
android:layout_width="match_parent" |
||||
android:layout_height="match_parent" |
||||
android:orientation="vertical" |
||||
> |
||||
|
||||
<include layout="@layout/layout_bar"/> |
||||
|
||||
<com.arialyy.simple.widget.SvgTextView |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:layout_marginLeft="16dp" |
||||
android:layout_marginRight="16dp" |
||||
android:layout_marginTop="16dp" |
||||
bind:iconClickListener="@{() -> viewModel.chooseUrl()}" |
||||
bind:svg_text_view_icon="@drawable/ic_modify" |
||||
bind:text="@{@string/url(url)}" |
||||
/> |
||||
|
||||
<com.arialyy.simple.widget.SvgTextView |
||||
android:layout_width="match_parent" |
||||
android:layout_height="wrap_content" |
||||
android:layout_marginLeft="16dp" |
||||
android:layout_marginRight="16dp" |
||||
android:layout_marginTop="8dp" |
||||
bind:iconClickListener="@{() -> viewModel.chooseFilePath()}" |
||||
bind:svg_text_view_icon="@drawable/ic_choose_file" |
||||
bind:text="@{@string/file_path(filePath)}" |
||||
/> |
||||
|
||||
<include |
||||
layout="@layout/layout_content_single" |
||||
bind:fileSize="@{fileSize}" |
||||
bind:progress="@{progress}" |
||||
bind:speed="@{speed}" |
||||
bind:stateStr="@{stateStr}" |
||||
/> |
||||
|
||||
|
||||
<!-- <com.arialyy.simple.widget.CodeView--> |
||||
<!-- android:id="@+id/code_view"--> |
||||
<!-- android:layout_width="match_parent"--> |
||||
<!-- android:layout_height="match_parent"--> |
||||
<!-- />--> |
||||
|
||||
|
||||
</LinearLayout> |
||||
</layout> |
Loading…
Reference in new issue