http group component

v4
laoyuyu 2 years ago
parent 49ccc1b28a
commit 16e76b42ed
  1. 41
      Http/src/main/java/com/arialyy/aria/http/BaseHttpThreadTaskAdapter.java
  2. 184
      Http/src/main/java/com/arialyy/aria/http/ConnectionHelp.java
  3. 9
      Http/src/main/java/com/arialyy/aria/http/HttpComponentLoader.kt
  4. 111
      Http/src/main/java/com/arialyy/aria/http/HttpRecordHandler.java
  5. 191
      Http/src/main/java/com/arialyy/aria/http/HttpTaskOption.java
  6. 14
      Http/src/main/java/com/arialyy/aria/http/download/HttpDStopController.kt
  7. 72
      Http/src/main/java/com/arialyy/aria/http/upload/HttpUBlockInterceptor.kt
  8. 94
      Http/src/main/java/com/arialyy/aria/http/upload/HttpULoader1.java
  9. 62
      Http/src/main/java/com/arialyy/aria/http/upload/HttpULoaderUtil.java
  10. 10
      Http/src/main/java/com/arialyy/aria/http/upload/HttpUTaskUtil.kt
  11. 470
      Http/src/main/java/com/arialyy/aria/http/upload/HttpUThreadTaskAdapter.java
  12. 2
      PublicComponent/src/main/java/com/arialyy/aria/core/inf/IComponentLoader.kt
  13. 2
      PublicComponent/src/main/java/com/arialyy/aria/core/listener/AbsEventListener.java
  14. 275
      PublicComponent/src/main/java/com/arialyy/aria/core/loader/UploadThreadStateManager.java
  15. 6
      app/build.gradle
  16. 5
      settings.gradle

@ -1,41 +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.http;
import com.arialyy.aria.core.common.AbsNormalEntity;
import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.task.AbsThreadTaskAdapter;
/**
* @author lyy
* Date: 2019-09-22
*/
public abstract class BaseHttpThreadTaskAdapter extends AbsThreadTaskAdapter {
protected HttpTaskOption mTaskOption;
protected BaseHttpThreadTaskAdapter(SubThreadConfig config) {
super(config);
mTaskOption = (HttpTaskOption) getTaskWrapper().getTaskOption();
}
protected String getFileName() {
return getEntity().getFileName();
}
protected AbsNormalEntity getEntity() {
return (AbsNormalEntity) getTaskWrapper().getEntity();
}
}

@ -1,184 +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.http;
import android.text.TextUtils;
import com.arialyy.aria.core.AriaConfig;
import com.arialyy.aria.core.ProtocolType;
import com.arialyy.aria.core.common.RequestEnum;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.SSLContextUtil;
import java.io.IOException;
import java.io.InputStream;
import java.net.CookieManager;
import java.net.CookieStore;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Set;
import java.util.zip.GZIPInputStream;
import java.util.zip.InflaterInputStream;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
/**
* Created by lyy on 2017/1/18. 链接帮助类
*/
public final class ConnectionHelp {
private static final String TAG = "ConnectionHelp";
/**
* 处理url参数
*/
public static URL handleUrl(String url, HttpOption option)
throws MalformedURLException {
Map<String, String> params = option.getParams();
if (params.isEmpty()) {
return new URL(CommonUtil.convertUrl(url));
}
if (option.getRequestMethod() == RequestEnum.GET) {
if (!url.contains("?")) {
url = url.concat("?");
}
StringBuilder sb = new StringBuilder();
sb.append(url).append("?");
Set<String> keys = params.keySet();
for (String key : keys) {
sb.append(URLEncoder.encode(key))
.append("=")
.append(URLEncoder.encode(params.get(key)))
.append("&");
}
String temp = sb.toString();
temp = temp.substring(0, temp.length() - 1);
return new URL(CommonUtil.convertUrl(temp));
}
if (option.getRequestMethod() == RequestEnum.POST) {
}
}
/**
* 处理链接
*
* @throws IOException
*/
public static HttpURLConnection handleConnection(URL url, HttpTaskOption taskDelegate)
throws IOException {
HttpURLConnection conn;
URLConnection urlConn;
if (taskDelegate.getProxy() != null) {
urlConn = url.openConnection(taskDelegate.getProxy());
} else {
urlConn = url.openConnection();
}
if (urlConn instanceof HttpsURLConnection) {
AriaConfig config = AriaConfig.getInstance();
conn = (HttpsURLConnection) urlConn;
SSLContext sslContext =
SSLContextUtil.getSSLContextFromAssets(config.getDConfig().getCaName(),
config.getDConfig().getCaPath(), ProtocolType.Default);
if (sslContext == null) {
sslContext = SSLContextUtil.getDefaultSLLContext(ProtocolType.Default);
}
SSLSocketFactory ssf = sslContext.getSocketFactory();
((HttpsURLConnection) conn).setSSLSocketFactory(ssf);
((HttpsURLConnection) conn).setHostnameVerifier(SSLContextUtil.HOSTNAME_VERIFIER);
} else {
conn = (HttpURLConnection) urlConn;
}
return conn;
}
/**
* 设置头部参数
*/
public static HttpURLConnection setConnectParam(HttpTaskOption delegate, HttpURLConnection conn) {
if (delegate.getRequestEnum() == RequestEnum.POST) {
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setUseCaches(false);
}
Set<String> keys = null;
if (delegate.getHeaders() != null && delegate.getHeaders().size() > 0) {
keys = delegate.getHeaders().keySet();
for (String key : keys) {
conn.setRequestProperty(key, delegate.getHeaders().get(key));
}
}
if (conn.getRequestProperty("Accept-Language") == null) {
conn.setRequestProperty("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,ja;q=0.7");
}
if (conn.getRequestProperty("Accept-Encoding") == null) {
conn.setRequestProperty("Accept-Encoding", "identity");
}
if (conn.getRequestProperty("Accept-Charset") == null) {
conn.setRequestProperty("Accept-Charset", "UTF-8");
}
if (conn.getRequestProperty("Connection") == null) {
conn.setRequestProperty("Connection", "Keep-Alive");
}
if (conn.getRequestProperty("Charset") == null) {
conn.setRequestProperty("Charset", "UTF-8");
}
if (conn.getRequestProperty("User-Agent") == null) {
conn.setRequestProperty("User-Agent",
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36");
}
if (conn.getRequestProperty("Accept") == null) {
StringBuilder accept = new StringBuilder();
accept.append("image/gif, ")
.append("image/jpeg, ")
.append("image/pjpeg, ")
.append("image/webp, ")
.append("image/apng, ")
.append("application/xml, ")
.append("application/xaml+xml, ")
.append("application/xhtml+xml, ")
.append("application/x-shockwave-flash, ")
.append("application/x-ms-xbap, ")
.append("application/x-ms-application, ")
.append("application/msword, ")
.append("application/vnd.ms-excel, ")
.append("application/vnd.ms-xpsdocument, ")
.append("application/vnd.ms-powerpoint, ")
.append("application/signed-exchange, ")
.append("text/plain, ")
.append("text/html, ")
.append("*/*");
conn.setRequestProperty("Accept", accept.toString());
}
//302获取重定向地址
conn.setInstanceFollowRedirects(false);
CookieManager manager = delegate.getCookieManager();
if (manager != null) {
CookieStore store = manager.getCookieStore();
if (store != null && store.getCookies().size() > 0) {
conn.setRequestProperty("Cookie",
TextUtils.join(";", store.getCookies()));
}
}
return conn;
}
}

@ -20,7 +20,6 @@ import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.inf.IBaseLoader import com.arialyy.aria.core.inf.IBaseLoader
import com.arialyy.aria.core.inf.IComponentLoader import com.arialyy.aria.core.inf.IComponentLoader
import com.arialyy.aria.core.inf.IDownloader import com.arialyy.aria.core.inf.IDownloader
import com.arialyy.aria.core.inf.IUploader
import com.arialyy.aria.http.download.HttpDownloader import com.arialyy.aria.http.download.HttpDownloader
import com.arialyy.aria.http.upload.HttpULoader import com.arialyy.aria.http.upload.HttpULoader
import kotlin.LazyThreadSafetyMode.SYNCHRONIZED import kotlin.LazyThreadSafetyMode.SYNCHRONIZED
@ -47,10 +46,10 @@ class HttpComponentLoader : IComponentLoader {
return downloader as T return downloader as T
} }
override fun <T : IUploader> upload(): T { // override fun <T : IUploader> upload(): T {
loader = uploader // loader = uploader
return uploader as T // return uploader as T
} // }
override fun getTaskEnum(): TaskEnum { override fun getTaskEnum(): TaskEnum {
return loader.getTaskEnum() return loader.getTaskEnum()

@ -1,111 +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.http;
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.DownloadEntity;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.util.RecordUtil;
import java.util.ArrayList;
/**
* @author lyy
* Date: 2019-09-23
*/
public final class HttpRecordHandler extends RecordHandler {
public HttpRecordHandler(AbsTaskWrapper wrapper) {
super(wrapper);
}
@Override public void handlerTaskRecord(TaskRecord record) {
RecordHelper helper = new RecordHelper(getWrapper(), record);
if (getWrapper().isSupportBP() && record.threadNum > 1) {
if (record.isBlock) {
helper.handleBlockRecord();
} else {
helper.handleMultiRecord();
}
} else if (!getWrapper().isSupportBP()) {
helper.handleNoSupportBPRecord();
} else {
helper.handleSingleThreadRecord();
}
}
@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;
int requestType = getWrapper().getRequestType();
if (requestType == ITaskWrapper.D_HTTP || requestType == ITaskWrapper.DG_HTTP) {
record.isBlock = Configuration.getInstance().downloadCfg.isUseBlock();
} else {
record.isBlock = false;
}
record.taskType = requestType;
record.isGroupRecord = getEntity().isGroupChild();
if (record.isGroupRecord) {
if (getEntity() instanceof DownloadEntity) {
record.dGroupHash = ((DownloadEntity) getEntity()).getGroupHash();
}
}
return record;
}
@Override public int initTaskThreadNum() {
int requestTpe = getWrapper().getRequestType();
if (requestTpe == ITaskWrapper.U_HTTP
|| (requestTpe == ITaskWrapper.D_HTTP && (!getWrapper().isSupportBP())
|| ((HttpTaskOption) getWrapper().getTaskOption()).isChunked())) {
return 1;
}
int threadNum = Configuration.getInstance().downloadCfg.getThreadNum();
return getFileSize() <= IRecordHandler.SUB_LEN
|| getEntity().isGroupChild()
|| threadNum == 1
? 1
: threadNum;
}
}

@ -1,191 +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.http;
import android.text.TextUtils;
import com.arialyy.aria.core.common.RequestEnum;
import com.arialyy.aria.core.inf.ITaskOption;
import com.arialyy.aria.core.processor.IHttpFileLenAdapter;
import com.arialyy.aria.core.processor.IHttpFileNameAdapter;
import java.lang.ref.SoftReference;
import java.net.CookieManager;
import java.net.Proxy;
import java.util.HashMap;
import java.util.Map;
/**
* Http任务设置的信息cookie请求参数
*/
public final class HttpTaskOption implements ITaskOption {
private CookieManager cookieManager;
/**
* 请求参数
*/
private Map<String, String> params;
/**
* http 请求头
*/
private Map<String, String> headers = new HashMap<>();
/**
* 字符编码默认为"utf-8"
*/
private String charSet = "utf-8";
/**
* 网络请求类型
*/
private RequestEnum requestEnum = RequestEnum.GET;
/**
* 是否使用服务器通过content-disposition传递的文件名内容格式{@code attachment; filename="filename.jpg"} {@code true}
* 使用
*/
private boolean useServerFileName = false;
/**
* 重定向链接
*/
private String redirectUrl = "";
/**
* 是否是chunk模式
*/
private boolean isChunked = false;
/**
* 文件上传需要的key
*/
private String attachment;
private Proxy proxy;
/**
* 文件上传表单
*/
private Map<String, String> formFields = new HashMap<>();
private SoftReference<IHttpFileLenAdapter> fileLenAdapter;
private SoftReference<IHttpFileNameAdapter> fileNameAdapter;
public IHttpFileLenAdapter getFileLenAdapter() {
return fileLenAdapter == null ? null : fileLenAdapter.get();
}
public IHttpFileNameAdapter getFileNameAdapter() {
return fileNameAdapter == null ? null : fileNameAdapter.get();
}
/**
* 如果是匿名内部类完成后需要将adapter设置为空否则会出现内存泄漏
*/
public void setFileLenAdapter(IHttpFileLenAdapter fileLenAdapter) {
this.fileLenAdapter = new SoftReference<>(fileLenAdapter);
}
public void setFileNameAdapter(IHttpFileNameAdapter fileNameAdapter) {
this.fileNameAdapter = new SoftReference<>(fileNameAdapter);
}
public Map<String, String> getFormFields() {
return formFields;
}
public void setFormFields(Map<String, String> formFields) {
this.formFields = formFields;
}
public String getAttachment() {
return TextUtils.isEmpty(attachment) ? "file" : attachment;
}
public void setAttachment(String attachment) {
this.attachment = attachment;
}
public boolean isChunked() {
return isChunked;
}
public void setChunked(boolean chunked) {
isChunked = chunked;
}
public CookieManager getCookieManager() {
return cookieManager;
}
public void setCookieManager(CookieManager cookieManager) {
this.cookieManager = cookieManager;
}
public Proxy getProxy() {
return proxy;
}
public void setProxy(Proxy proxy) {
this.proxy = proxy;
}
public Map<String, String> getHeaders() {
return headers;
}
public void setHeaders(Map<String, String> headers) {
this.headers = headers;
}
public String getCharSet() {
return TextUtils.isEmpty(charSet) ? "utf-8" : charSet;
}
public void setCharSet(String charSet) {
this.charSet = charSet;
}
public RequestEnum getRequestEnum() {
return requestEnum;
}
public void setRequestEnum(RequestEnum requestEnum) {
this.requestEnum = requestEnum;
}
public boolean isUseServerFileName() {
return useServerFileName;
}
public void setUseServerFileName(boolean useServerFileName) {
this.useServerFileName = useServerFileName;
}
public String getRedirectUrl() {
return redirectUrl;
}
public void setRedirectUrl(String redirectUrl) {
this.redirectUrl = redirectUrl;
}
public Map<String, String> getParams() {
return params;
}
public void setParams(Map<String, String> params) {
this.params = params;
}
}

@ -44,4 +44,18 @@ class HttpDStopController(val taskId: Int) {
HttpDStopController2(Uri.parse(task.filePath)).stop() HttpDStopController2(Uri.parse(task.filePath)).stop()
} }
fun resume() {
val task = TaskCachePool.getTask(taskId)
if (task == null) {
Timber.e("task not found, taskId: $taskId")
return
}
val util = TaskCachePool.getTaskUtil(Uri.parse(task.filePath))
if (util == null) {
Timber.e("resume fail, please restart task, taskId: $taskId")
return
}
util.start()
}
} }

@ -1,31 +1,41 @@
/* ///*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) // * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
* // *
* Licensed under the Apache License, Version 2.0 (the "License"); // * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. // * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at // * You may obtain a copy of the License at
* // *
* http://www.apache.org/licenses/LICENSE-2.0 // * http://www.apache.org/licenses/LICENSE-2.0
* // *
* Unless required by applicable law or agreed to in writing, software // * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, // * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and // * See the License for the specific language governing permissions and
* limitations under the License. // * limitations under the License.
*/ // */
package com.arialyy.aria.http.upload //package com.arialyy.aria.http.upload
//
import com.arialyy.aria.core.task.ITaskInterceptor //import com.arialyy.aria.core.inf.IBlockManager
import com.arialyy.aria.core.task.TaskChain //import com.arialyy.aria.core.task.ITask
import com.arialyy.aria.core.task.TaskResp //import com.arialyy.aria.core.task.ITaskInterceptor
//import com.arialyy.aria.core.task.TaskChain
/** //import com.arialyy.aria.core.task.TaskResp
* @Author laoyuyu //import com.arialyy.aria.http.HttpTaskOption
* @Description //import com.arialyy.aria.orm.entity.TaskRecord
* @Date 9:47 PM 2023/2/21 //
**/ ///**
class HttpUBlockInterceptor: ITaskInterceptor { // * @Author laoyuyu
override suspend fun interceptor(chain: TaskChain): TaskResp { // * @Description
// * @Date 9:47 PM 2023/2/21
} // **/
} //class HttpUBlockInterceptor: ITaskInterceptor {
//
// private lateinit var task: ITask
// private lateinit var option: HttpTaskOption
// private lateinit var blockManager: IBlockManager
// private lateinit var taskRecord: TaskRecord
//
// override suspend fun interceptor(chain: TaskChain): TaskResp {
//
// }
//}

@ -1,94 +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.http.upload;
import android.os.Handler;
import android.os.Looper;
import com.arialyy.aria.core.inf.IBlockManager;
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.exception.AriaHTTPException;
import com.arialyy.aria.util.ALog;
import java.util.List;
final class HttpULoader1 extends AbsNormalLoader<UTaskWrapper> {
HttpULoader1(UTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
}
@Override public void addComponent(IRecordHandler recordHandler) {
mRecordHandler = recordHandler;
}
/**
* @deprecated http 上传任务不需要设置这个
*/
@Deprecated
@Override public void addComponent(IInfoTask infoTask) {
}
@Override public void addComponent(IBlockManager threadState) {
mStateManager = threadState;
}
@Override public void addComponent(IThreadTaskBuilder builder) {
mTTBuilder = builder;
}
@Override protected void handleTask(Looper looper) {
mRecord = mRecordHandler.getRecord(getFileSize());
mStateManager.setLooper(mRecord, looper);
List<IThreadTask> tt = mTTBuilder.buildThreadTask(mRecord,
new Handler(looper, mStateManager.getHandlerCallback()));
if (tt == null || tt.isEmpty()) {
ALog.e(TAG, "创建线程任务失败");
getListener().onFail(false, new AriaHTTPException("创建线程任务失败"));
return;
}
getListener().onStart(0);
ThreadTaskManager.getInstance().startThread(mTaskWrapper.getKey(), tt.get(0));
startTimer();
}
@Override public long getFileSize() {
return mTaskWrapper.getEntity().getFileSize();
}
@Override protected void checkComponent() {
if (mRecordHandler == null) {
throw new NullPointerException("任务记录组件为空");
}
if (mStateManager == null) {
throw new NullPointerException("任务状态管理组件为空");
}
if (mTTBuilder == null) {
throw new NullPointerException("线程任务组件为空");
}
}
@Override public long getCurrentProgress() {
return mStateManager.getCurrentProgress();
}
}

@ -1,62 +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.http.upload;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.loader.AbsNormalLoader;
import com.arialyy.aria.core.loader.AbsNormalLoaderUtil;
import com.arialyy.aria.core.loader.AbsNormalTTBuilderAdapter;
import com.arialyy.aria.core.loader.LoaderStructure;
import com.arialyy.aria.core.loader.NormalTTBuilder;
import com.arialyy.aria.core.loader.UploadThreadStateManager;
import com.arialyy.aria.core.task.IThreadTaskAdapter;
import com.arialyy.aria.core.upload.UTaskWrapper;
import com.arialyy.aria.http.HttpRecordHandler;
import com.arialyy.aria.http.HttpTaskOption;
/**
* @author lyy
* Date: 2019-09-19
*/
public final class HttpULoaderUtil extends AbsNormalLoaderUtil {
@Override public AbsNormalLoader getLoader() {
if (mLoader == null) {
getTaskWrapper().generateTaskOption(HttpTaskOption.class);
mLoader = new HttpULoader1((UTaskWrapper) getTaskWrapper(), getListener());
}
return mLoader;
}
@Override public LoaderStructure BuildLoaderStructure() {
LoaderStructure structure = new LoaderStructure();
structure.addComponent(new HttpRecordHandler(getTaskWrapper()))
// .addComponent(new NormalThreadStateManager(getListener()))
.addComponent(new UploadThreadStateManager(getListener()))
.addComponent(new NormalTTBuilder(getTaskWrapper(), new AbsNormalTTBuilderAdapter() {
@Override public IThreadTaskAdapter getAdapter(SubThreadConfig config) {
return new HttpUThreadTaskAdapter(config);
}
@Override public boolean handleNewTask(TaskRecord record, int totalThreadNum) {
return true;
}
}));
structure.accept(getLoader());
return structure;
}
}

@ -19,6 +19,7 @@ import android.os.Looper
import com.arialyy.aria.core.DuaContext import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.inf.IBlockManager import com.arialyy.aria.core.inf.IBlockManager
import com.arialyy.aria.core.task.AbsTaskUtil import com.arialyy.aria.core.task.AbsTaskUtil
import com.arialyy.aria.core.task.BlockManager
import com.arialyy.aria.core.task.TaskResp import com.arialyy.aria.core.task.TaskResp
import com.arialyy.aria.exception.AriaException import com.arialyy.aria.exception.AriaException
import com.arialyy.aria.http.HttpTaskOption import com.arialyy.aria.http.HttpTaskOption
@ -35,12 +36,17 @@ import kotlinx.coroutines.launch
* @Date 9:21 PM 2023/2/21 * @Date 9:21 PM 2023/2/21
**/ **/
class HttpUTaskUtil : AbsTaskUtil() { class HttpUTaskUtil : AbsTaskUtil() {
private var blockManager: BlockManager? = null
override fun getBlockManager(): IBlockManager { override fun getBlockManager(): IBlockManager {
TODO("Not yet implemented") if (blockManager == null) {
blockManager = BlockManager(getTask())
}
return blockManager!!
} }
override fun isRunning(): Boolean { override fun isRunning(): Boolean {
TODO("Not yet implemented") return blockManager?.isRunning ?: false
} }
override fun cancel() { override fun cancel() {

@ -1,235 +1,235 @@
/* ///*
* Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) // * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria)
* // *
* Licensed under the Apache License, Version 2.0 (the "License"); // * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. // * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at // * You may obtain a copy of the License at
* // *
* http://www.apache.org/licenses/LICENSE-2.0 // * http://www.apache.org/licenses/LICENSE-2.0
* // *
* Unless required by applicable law or agreed to in writing, software // * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, // * distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and // * See the License for the specific language governing permissions and
* limitations under the License. // * limitations under the License.
*/ // */
package com.arialyy.aria.http.upload; //package com.arialyy.aria.http.upload;
//
import android.text.TextUtils; //import android.text.TextUtils;
import com.arialyy.aria.core.common.SubThreadConfig; //import com.arialyy.aria.core.common.SubThreadConfig;
import com.arialyy.aria.core.upload.UploadEntity; //import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.exception.AriaHTTPException; //import com.arialyy.aria.exception.AriaHTTPException;
import com.arialyy.aria.http.BaseHttpThreadTaskAdapter; //import com.arialyy.aria.http.BaseHttpThreadTaskAdapter;
import com.arialyy.aria.http.ConnectionHelp; //import com.arialyy.aria.http.ConnectionHelp;
import com.arialyy.aria.util.ALog; //import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil; //import com.arialyy.aria.util.CommonUtil;
import java.io.BufferedReader; //import java.io.BufferedReader;
import java.io.File; //import java.io.File;
import java.io.FileInputStream; //import java.io.FileInputStream;
import java.io.FileOutputStream; //import java.io.FileOutputStream;
import java.io.IOException; //import java.io.IOException;
import java.io.InputStreamReader; //import java.io.InputStreamReader;
import java.io.OutputStream; //import java.io.OutputStream;
import java.io.OutputStreamWriter; //import java.io.OutputStreamWriter;
import java.io.PrintWriter; //import java.io.PrintWriter;
import java.net.HttpURLConnection; //import java.net.HttpURLConnection;
import java.net.URL; //import java.net.URL;
import java.net.URLConnection; //import java.net.URLConnection;
import java.util.Map; //import java.util.Map;
import java.util.Set; //import java.util.Set;
import java.util.UUID; //import java.util.UUID;
//
/** ///**
* Created by Aria.Lao on 2017/7/28. 不支持断点的HTTP上传任务 // * Created by Aria.Lao on 2017/7/28. 不支持断点的HTTP上传任务
*/ // */
final class HttpUThreadTaskAdapter extends BaseHttpThreadTaskAdapter { //final class HttpUThreadTaskAdapter extends BaseHttpThreadTaskAdapter {
//
private final String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成 // private final String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成
private final String PREFIX = "--", LINE_END = "\r\n"; // private final String PREFIX = "--", LINE_END = "\r\n";
private HttpURLConnection mHttpConn; // private HttpURLConnection mHttpConn;
private OutputStream mOutputStream; // private OutputStream mOutputStream;
//
HttpUThreadTaskAdapter(SubThreadConfig config) { // HttpUThreadTaskAdapter(SubThreadConfig config) {
super(config); // super(config);
} // }
//
@Override protected void handlerThreadTask() { // @Override protected void handlerThreadTask() {
File uploadFile = new File(getEntity().getFilePath()); // File uploadFile = new File(getEntity().getFilePath());
if (!uploadFile.exists()) { // if (!uploadFile.exists()) {
fail(new AriaHTTPException( // fail(new AriaHTTPException(
String.format("上传失败,文件不存在;filePath: %s, url: %s", getEntity().getFilePath(), // String.format("上传失败,文件不存在;filePath: %s, url: %s", getEntity().getFilePath(),
getEntity().getUrl()))); // getEntity().getUrl())));
return; // return;
} // }
URL url; // URL url;
try { // try {
url = new URL(CommonUtil.convertUrl(getThreadConfig().url)); // url = new URL(CommonUtil.convertUrl(getThreadConfig().url));
//
mHttpConn = (HttpURLConnection) url.openConnection(); // mHttpConn = (HttpURLConnection) url.openConnection();
mHttpConn.setRequestMethod(mTaskOption.getRequestEnum().name); // mHttpConn.setRequestMethod(mTaskOption.getRequestEnum().name);
mHttpConn.setUseCaches(false); // mHttpConn.setUseCaches(false);
mHttpConn.setDoOutput(true); // mHttpConn.setDoOutput(true);
mHttpConn.setDoInput(true); // mHttpConn.setDoInput(true);
mHttpConn.setRequestProperty("Connection", "Keep-Alive"); // mHttpConn.setRequestProperty("Connection", "Keep-Alive");
mHttpConn.setRequestProperty("Content-Type", // mHttpConn.setRequestProperty("Content-Type",
getContentType() + "; boundary=" + BOUNDARY); // getContentType() + "; boundary=" + BOUNDARY);
mHttpConn.setRequestProperty("User-Agent", getUserAgent()); // mHttpConn.setRequestProperty("User-Agent", getUserAgent());
mHttpConn.setConnectTimeout(getTaskConfig().getConnectTimeOut()); // mHttpConn.setConnectTimeout(getTaskConfig().getConnectTimeOut());
mHttpConn.setReadTimeout(getTaskConfig().getIOTimeOut()); // mHttpConn.setReadTimeout(getTaskConfig().getIOTimeOut());
//内部缓冲区---分段上传防止oom // //内部缓冲区---分段上传防止oom
mHttpConn.setChunkedStreamingMode(getTaskConfig().getBuffSize()); // mHttpConn.setChunkedStreamingMode(getTaskConfig().getBuffSize());
//
//添加Http请求头部 // //添加Http请求头部
Set<String> keys = mTaskOption.getHeaders().keySet(); // Set<String> keys = mTaskOption.getHeaders().keySet();
for (String key : keys) { // for (String key : keys) {
mHttpConn.setRequestProperty(key, mTaskOption.getHeaders().get(key)); // mHttpConn.setRequestProperty(key, mTaskOption.getHeaders().get(key));
} // }
mOutputStream = mHttpConn.getOutputStream(); // mOutputStream = mHttpConn.getOutputStream();
PrintWriter writer = // PrintWriter writer =
new PrintWriter(new OutputStreamWriter(mOutputStream, mTaskOption.getCharSet()), true); // new PrintWriter(new OutputStreamWriter(mOutputStream, mTaskOption.getCharSet()), true);
// 添加参数 // // 添加参数
Map<String, String> params = mTaskOption.getParams(); // Map<String, String> params = mTaskOption.getParams();
if (params != null && !params.isEmpty()) { // if (params != null && !params.isEmpty()) {
for (String key : params.keySet()) { // for (String key : params.keySet()) {
addFormField(writer, key, params.get(key)); // addFormField(writer, key, params.get(key));
} // }
} // }
//
//添加文件上传表单字段 // //添加文件上传表单字段
keys = mTaskOption.getFormFields().keySet(); // keys = mTaskOption.getFormFields().keySet();
for (String key : keys) { // for (String key : keys) {
addFormField(writer, key, mTaskOption.getFormFields().get(key)); // addFormField(writer, key, mTaskOption.getFormFields().get(key));
} // }
//
uploadFile(writer, mTaskOption.getAttachment(), uploadFile); // uploadFile(writer, mTaskOption.getAttachment(), uploadFile);
finish(writer); // finish(writer);
} catch (Exception e) { // } catch (Exception e) {
e.printStackTrace(); // e.printStackTrace();
fail(new AriaHTTPException( // fail(new AriaHTTPException(
String.format("上传失败,filePath: %s, url: %s", getEntity().getFilePath(), // String.format("上传失败,filePath: %s, url: %s", getEntity().getFilePath(),
getEntity().getUrl()), e)); // getEntity().getUrl()), e));
} // }
} // }
//
private void fail(AriaHTTPException e1) { // private void fail(AriaHTTPException e1) {
try { // try {
fail(e1, false); // fail(e1, false);
if (mOutputStream != null) { // if (mOutputStream != null) {
mOutputStream.close(); // mOutputStream.close();
} // }
} catch (IOException e) { // } catch (IOException e) {
e.printStackTrace(); // e.printStackTrace();
} // }
} // }
//
private String getContentType() { // private String getContentType() {
//return (mTaskOption.getHeaders() == null || TextUtils.isEmpty( // //return (mTaskOption.getHeaders() == null || TextUtils.isEmpty(
// mTaskOption.getHeaders().get("Content-Type"))) ? "multipart/form-data" // // mTaskOption.getHeaders().get("Content-Type"))) ? "multipart/form-data"
// : mTaskOption.getHeaders().get("Content-Type"); // // : mTaskOption.getHeaders().get("Content-Type");
return "multipart/form-data"; // return "multipart/form-data";
} // }
//
private String getUserAgent() { // private String getUserAgent() {
return (mTaskOption.getHeaders() == null || TextUtils.isEmpty( // return (mTaskOption.getHeaders() == null || TextUtils.isEmpty(
mTaskOption.getHeaders().get("User-Agent"))) // mTaskOption.getHeaders().get("User-Agent")))
? "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)" // ? "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)"
: mTaskOption.getHeaders().get("User-Agent"); // : mTaskOption.getHeaders().get("User-Agent");
} // }
//
/** // /**
* 添加文件上传表单字段 // * 添加文件上传表单字段
*/ // */
private void addFormField(PrintWriter writer, String name, String value) { // private void addFormField(PrintWriter writer, String name, String value) {
writer.append(PREFIX).append(BOUNDARY).append(LINE_END); // writer.append(PREFIX).append(BOUNDARY).append(LINE_END);
writer.append("Content-Disposition: form-data; name=\"") // writer.append("Content-Disposition: form-data; name=\"")
.append(name) // .append(name)
.append("\"") // .append("\"")
.append(LINE_END); // .append(LINE_END);
writer.append("Content-Type: text/plain; charset=") // writer.append("Content-Type: text/plain; charset=")
.append(mTaskOption.getCharSet()) // .append(mTaskOption.getCharSet())
.append(LINE_END); // .append(LINE_END);
writer.append(LINE_END); // writer.append(LINE_END);
writer.append(value).append(LINE_END); // writer.append(value).append(LINE_END);
writer.flush(); // writer.flush();
} // }
//
/** // /**
* 上传文件 // * 上传文件
* // *
* @param attachment 文件上传attachment // * @param attachment 文件上传attachment
* @throws IOException // * @throws IOException
*/ // */
private void uploadFile(PrintWriter writer, String attachment, File uploadFile) // private void uploadFile(PrintWriter writer, String attachment, File uploadFile)
throws IOException { // throws IOException {
writer.append(PREFIX).append(BOUNDARY).append(LINE_END); // writer.append(PREFIX).append(BOUNDARY).append(LINE_END);
writer.append("Content-Disposition: form-data; name=\"") // writer.append("Content-Disposition: form-data; name=\"")
.append(attachment) // .append(attachment)
.append("\"; filename=\"") // .append("\"; filename=\"")
.append(getEntity().getFileName()) // .append(getEntity().getFileName())
.append("\"") // .append("\"")
.append(LINE_END); // .append(LINE_END);
writer.append("Content-Type: ") // writer.append("Content-Type: ")
.append(URLConnection.guessContentTypeFromName(getEntity().getFileName())) // .append(URLConnection.guessContentTypeFromName(getEntity().getFileName()))
.append(LINE_END); // .append(LINE_END);
writer.append("Content-Transfer-Encoding: binary").append(LINE_END); // writer.append("Content-Transfer-Encoding: binary").append(LINE_END);
writer.append(LINE_END); // writer.append(LINE_END);
writer.flush(); // writer.flush();
//
FileInputStream inputStream = new FileInputStream(uploadFile); // FileInputStream inputStream = new FileInputStream(uploadFile);
byte[] buffer = new byte[4096]; // byte[] buffer = new byte[4096];
int bytesLen; // int bytesLen;
while ((bytesLen = inputStream.read(buffer)) != -1) { // while ((bytesLen = inputStream.read(buffer)) != -1) {
mOutputStream.write(buffer, 0, bytesLen); // mOutputStream.write(buffer, 0, bytesLen);
progress(bytesLen); // progress(bytesLen);
if (getThreadTask().isBreak()) { // if (getThreadTask().isBreak()) {
break; // break;
} // }
if (mSpeedBandUtil != null) { // if (mSpeedBandUtil != null) {
mSpeedBandUtil.limitNextBytes(bytesLen); // mSpeedBandUtil.limitNextBytes(bytesLen);
} // }
} // }
//
mOutputStream.flush(); // mOutputStream.flush();
inputStream.close(); // inputStream.close();
writer.append(LINE_END).flush(); // writer.append(LINE_END).flush();
// 保证上传的文件和本地的一致,https://www.cnblogs.com/tugenhua0707/p/8975121.html // // 保证上传的文件和本地的一致,https://www.cnblogs.com/tugenhua0707/p/8975121.html
writer.append(PREFIX).append(BOUNDARY).append(PREFIX).append(LINE_END).flush(); // writer.append(PREFIX).append(BOUNDARY).append(PREFIX).append(LINE_END).flush();
} // }
//
/** // /**
* 任务结束操作 // * 任务结束操作
* // *
* @throws IOException // * @throws IOException
*/ // */
private String finish(PrintWriter writer) throws IOException { // private String finish(PrintWriter writer) throws IOException {
StringBuilder response = new StringBuilder(); // StringBuilder response = new StringBuilder();
int status = mHttpConn.getResponseCode(); // int status = mHttpConn.getResponseCode();
//
if (status == HttpURLConnection.HTTP_OK) { // if (status == HttpURLConnection.HTTP_OK) {
BufferedReader reader = // BufferedReader reader =
new BufferedReader(new InputStreamReader(ConnectionHelp.convertInputStream(mHttpConn))); // new BufferedReader(new InputStreamReader(ConnectionHelp.convertInputStream(mHttpConn)));
String line; // String line;
while (getThreadTask().isLive() && (line = reader.readLine()) != null) { // while (getThreadTask().isLive() && (line = reader.readLine()) != null) {
response.append(line); // response.append(line);
} // }
reader.close(); // reader.close();
mHttpConn.disconnect(); // mHttpConn.disconnect();
getEntity().setResponseStr(response.toString()); // getEntity().setResponseStr(response.toString());
complete(); // complete();
} else { // } else {
String msg = "response msg: " + mHttpConn.getResponseMessage() + ",code: " + status; // String msg = "response msg: " + mHttpConn.getResponseMessage() + ",code: " + status;
ALog.e(TAG, msg); // ALog.e(TAG, msg);
getEntity().setResponseStr(response.toString()); // getEntity().setResponseStr(response.toString());
fail(new AriaHTTPException(msg), false); // fail(new AriaHTTPException(msg), false);
response.append(status); // response.append(status);
} // }
writer.flush(); // writer.flush();
writer.close(); // writer.close();
mOutputStream.close(); // mOutputStream.close();
return response.toString(); // return response.toString();
} // }
//
@Override protected UploadEntity getEntity() { // @Override protected UploadEntity getEntity() {
return (UploadEntity) super.getEntity(); // return (UploadEntity) super.getEntity();
} // }
} //}

@ -32,7 +32,7 @@ interface IComponentLoader {
fun <T : IDownloader> download(): T fun <T : IDownloader> download(): T
fun <T : IUploader> upload(): T // fun <T : IUploader> upload(): T
fun getTaskEnum(): TaskEnum fun getTaskEnum(): TaskEnum
} }

@ -144,7 +144,7 @@ public abstract class AbsEventListener implements IEventListener {
TaskCachePool.INSTANCE.removeTask(getTask().getTaskId()); TaskCachePool.INSTANCE.removeTask(getTask().getTaskId());
return; return;
} }
if (state == IEntity.STATE_COMPLETE || state == IEntity.STATE_STOP) { if (state == IEntity.STATE_COMPLETE) {
TaskCachePool.INSTANCE.removeTask(getTask().getTaskId()); TaskCachePool.INSTANCE.removeTask(getTask().getTaskId());
} }

@ -1,275 +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.core.loader;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.inf.IBlockManager;
import com.arialyy.aria.core.listener.IEventListener;
import com.arialyy.aria.exception.AriaException;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.CommonUtil;
import com.arialyy.aria.util.FileUtil;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
/**
* 线程任务管理器用于处理多线程下载时任务的状态回调
*/
public class UploadThreadStateManager implements IBlockManager {
private final String TAG = CommonUtil.getClassName(this);
/**
* 任务状态回调
*/
private IEventListener mListener;
private int mThreadNum; // 启动的线程总数
private AtomicInteger mCancelNum = new AtomicInteger(0); // 已经取消的线程的数
private AtomicInteger mStopNum = new AtomicInteger(0); // 已经停止的线程数
private AtomicInteger mFailNum = new AtomicInteger(0); // 失败的线程数
private AtomicInteger mCompleteNum = new AtomicInteger(0); // 完成的线程数
private long mProgress; //当前总进度
private TaskRecord mTaskRecord; // 任务记录
private Looper mLooper;
/**
* @param listener 任务事件
*/
public UploadThreadStateManager(IEventListener listener) {
mListener = listener;
}
@Override public void setLooper(TaskRecord taskRecord, Looper looper) {
mTaskRecord = taskRecord;
mThreadNum = mTaskRecord.threadNum;
mLooper = looper;
}
private void checkLooper() {
if (mTaskRecord == null) {
throw new NullPointerException("任务记录为空");
}
if (mLooper == null) {
throw new NullPointerException("Looper为空");
}
}
private Handler.Callback callback = new Handler.Callback() {
@Override public boolean handleMessage(Message msg) {
checkLooper();
switch (msg.what) {
case STATE_STOP:
mStopNum.getAndIncrement();
if (isStop()) {
quitLooper();
}
break;
case STATE_CANCEL:
mCancelNum.getAndIncrement();
if (isCancel()) {
quitLooper();
}
break;
case STATE_FAIL:
mFailNum.getAndIncrement();
if (hasFailedBlock()) {
Bundle b = msg.getData();
mListener.onFail(b.getBoolean(DATA_RETRY, false),
(AriaException) b.getSerializable(DATA_ERROR_INFO));
quitLooper();
}
break;
case STATE_COMPLETE:
mCompleteNum.getAndIncrement();
if (isCompleted()) {
ALog.d(TAG, "isComplete, completeNum = " + mCompleteNum);
//上传文件不需要合并文件
mListener.onComplete();
quitLooper();
}
break;
case STATE_RUNNING:
Bundle b = msg.getData();
if (b != null) {
long len = b.getLong(IBlockManager.DATA_ADD_LEN, 0);
mProgress += len;
}
break;
case STATE_UPDATE_PROGRESS:
if (msg.obj == null) {
mProgress = updateBlockProgress();
} else if (msg.obj instanceof Long) {
mProgress = (long) msg.obj;
}
break;
}
return false;
}
};
@Override public void updateCurrentProgress(long currentProgress) {
mProgress = currentProgress;
}
/**
* 退出looper循环
*/
private void quitLooper() {
mLooper.quit();
}
/**
* 获取当前任务下载进度
*
* @return 当前任务下载进度
*/
@Override
public long getCurrentProgress() {
return mProgress;
}
@Override public Handler.Callback getHandlerCallback() {
return callback;
}
/**
* 所有子线程是否都已经停止
*/
public boolean isStop() {
//ALog.d(TAG,
// String.format("isStop; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s", mStopNum,
// mCancelNum, mFailNum, mCompleteNum));
return mStopNum.get() == mThreadNum || mStopNum.get() + mCompleteNum.get() == mThreadNum;
}
/**
* 所有子线程是否都已经失败
*/
@Override
public boolean hasFailedBlock() {
//ALog.d(TAG,
// String.format("isFail; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s", mStopNum,
// mCancelNum, mFailNum, mCompleteNum));
return mCompleteNum.get() != mThreadNum
&& (mFailNum.get() == mThreadNum || mFailNum.get() + mCompleteNum.get() == mThreadNum);
}
/**
* 所有子线程是否都已经完成
*/
@Override
public boolean isCompleted() {
//ALog.d(TAG,
// String.format("isComplete; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s",
// mStopNum,
// mCancelNum, mFailNum, mCompleteNum));
return mCompleteNum.get() == mThreadNum;
}
/**
* 所有子线程是否都已经取消
*/
public boolean isCancel() {
//ALog.d(TAG, String.format("isCancel; stopNum: %s, cancelNum: %s, failNum: %s, completeNum: %s",
// mStopNum,
// mCancelNum, mFailNum, mCompleteNum));
return mCancelNum.get() == mThreadNum;
}
/**
* 更新分块任务s的真实进度
*/
private long updateBlockProgress() {
long size = 0;
for (int i = 0, len = mTaskRecord.threadRecords.size(); i < len; i++) {
File temp = new File(String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, i));
if (temp.exists()) {
size += temp.length();
}
}
return size;
}
/**
* 合并sftp的分块
*/
private boolean mergerSFtp() {
if (mTaskRecord.threadNum == 1) {
File partFile = new File(String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, 0));
return partFile.renameTo(new File(mTaskRecord.filePath));
}
List<String> partPath = new ArrayList<>();
for (int i = 0, len = mTaskRecord.threadNum; i < len; i++) {
partPath.add(String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, i));
}
FileUtil.mergeSFtpFile(mTaskRecord.filePath, partPath, mTaskRecord.fileLength);
for (String pp : partPath) {
FileUtil.deleteFile(pp);
}
return true;
}
/**
* 合并文件
*
* @return {@code true} 合并成功{@code false}合并失败
*/
private boolean mergeFile() {
if (mTaskRecord.threadNum == 1) {
File targetFile = new File(mTaskRecord.filePath);
if (targetFile.exists() && targetFile.length() == mTaskRecord.fileLength){
return true;
}
FileUtil.deleteFile(targetFile);
File partFile = new File(String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, 0));
return partFile.renameTo(targetFile);
}
List<String> partPath = new ArrayList<>();
for (int i = 0, len = mTaskRecord.threadNum; i < len; i++) {
partPath.add(String.format(IRecordHandler.SUB_PATH, mTaskRecord.filePath, i));
}
boolean isSuccess = FileUtil.mergeFile(mTaskRecord.filePath, partPath);
if (isSuccess) {
for (String pp : partPath) {
FileUtil.deleteFile(pp);
}
File targetFile = new File(mTaskRecord.filePath);
if (targetFile.exists() && targetFile.length() > mTaskRecord.fileLength) {
ALog.e(TAG, String.format("任务【%s】分块文件合并失败,下载长度超出文件真实长度,downloadLen: %s,fileSize: %s",
targetFile.getName(), targetFile.length(), mTaskRecord.fileLength));
return false;
}
return true;
} else {
ALog.e(TAG, "合并失败");
return false;
}
}
@Override public void accept(ILoaderVisitor visitor) {
visitor.addComponent(this);
}
}

@ -76,10 +76,10 @@ dependencies {
// aria // aria
kapt project(':AriaCompiler') kapt project(':AriaCompiler')
implementation project(':Aria') implementation project(':Aria')
implementation project(':M3U8Component') // implementation project(':M3U8Component')
implementation project(':FtpComponent') // implementation project(':FtpComponent')
implementation project(path: ':AriaAnnotations') implementation project(path: ':AriaAnnotations')
implementation project(path: ':SFtpComponent') // implementation project(path: ':SFtpComponent')
// implementation 'com.arialyy.aria:core:3.8.12' // implementation 'com.arialyy.aria:core:3.8.12'

@ -55,8 +55,9 @@ gradle.rootProject {
} }
def componentList = [':app', ':Aria', ':AriaAnnotations', ':AriaCompiler', def componentList = [':app', ':Aria', ':AriaAnnotations', ':AriaCompiler',
':AppFrame', ':Http', ':M3U8Component', ':SFtpComponent', ':FtpComponent', ':PublicComponent', ':AppFrame', ':Http', ':PublicComponent', ':Queue', ':Schedulers',
':Queue', ':Schedulers', ":HttpGroup" // ':M3U8Component', ':SFtpComponent', ':FtpComponent',
":HttpGroup"
] ]
componentList.forEach { componentList.forEach {

Loading…
Cancel
Save