parent
49ccc1b28a
commit
16e76b42ed
@ -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; |
|
||||||
} |
|
||||||
} |
|
@ -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; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
@ -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; |
|
||||||
} |
|
||||||
} |
|
@ -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(
|
||||||
|
// // mTaskOption.getHeaders().get("Content-Type"))) ? "multipart/form-data"
|
||||||
|
// // : mTaskOption.getHeaders().get("Content-Type");
|
||||||
|
// return "multipart/form-data";
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// private String getUserAgent() {
|
||||||
// return (mTaskOption.getHeaders() == null || TextUtils.isEmpty(
|
// return (mTaskOption.getHeaders() == null || TextUtils.isEmpty(
|
||||||
// mTaskOption.getHeaders().get("Content-Type"))) ? "multipart/form-data"
|
// mTaskOption.getHeaders().get("User-Agent")))
|
||||||
// : mTaskOption.getHeaders().get("Content-Type");
|
// ? "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)"
|
||||||
return "multipart/form-data"; |
// : mTaskOption.getHeaders().get("User-Agent");
|
||||||
} |
// }
|
||||||
|
//
|
||||||
private String getUserAgent() { |
// /**
|
||||||
return (mTaskOption.getHeaders() == null || TextUtils.isEmpty( |
// * 添加文件上传表单字段
|
||||||
mTaskOption.getHeaders().get("User-Agent"))) |
// */
|
||||||
? "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)" |
// private void addFormField(PrintWriter writer, String name, String value) {
|
||||||
: mTaskOption.getHeaders().get("User-Agent"); |
// writer.append(PREFIX).append(BOUNDARY).append(LINE_END);
|
||||||
} |
// writer.append("Content-Disposition: form-data; name=\"")
|
||||||
|
// .append(name)
|
||||||
/** |
// .append("\"")
|
||||||
* 添加文件上传表单字段 |
// .append(LINE_END);
|
||||||
*/ |
// writer.append("Content-Type: text/plain; charset=")
|
||||||
private void addFormField(PrintWriter writer, String name, String value) { |
// .append(mTaskOption.getCharSet())
|
||||||
writer.append(PREFIX).append(BOUNDARY).append(LINE_END); |
// .append(LINE_END);
|
||||||
writer.append("Content-Disposition: form-data; name=\"") |
// writer.append(LINE_END);
|
||||||
.append(name) |
// writer.append(value).append(LINE_END);
|
||||||
.append("\"") |
// writer.flush();
|
||||||
.append(LINE_END); |
// }
|
||||||
writer.append("Content-Type: text/plain; charset=") |
//
|
||||||
.append(mTaskOption.getCharSet()) |
// /**
|
||||||
.append(LINE_END); |
// * 上传文件
|
||||||
writer.append(LINE_END); |
// *
|
||||||
writer.append(value).append(LINE_END); |
// * @param attachment 文件上传attachment
|
||||||
writer.flush(); |
// * @throws IOException
|
||||||
} |
// */
|
||||||
|
// private void uploadFile(PrintWriter writer, String attachment, File uploadFile)
|
||||||
/** |
// throws IOException {
|
||||||
* 上传文件 |
// writer.append(PREFIX).append(BOUNDARY).append(LINE_END);
|
||||||
* |
// writer.append("Content-Disposition: form-data; name=\"")
|
||||||
* @param attachment 文件上传attachment |
// .append(attachment)
|
||||||
* @throws IOException |
// .append("\"; filename=\"")
|
||||||
*/ |
// .append(getEntity().getFileName())
|
||||||
private void uploadFile(PrintWriter writer, String attachment, File uploadFile) |
// .append("\"")
|
||||||
throws IOException { |
// .append(LINE_END);
|
||||||
writer.append(PREFIX).append(BOUNDARY).append(LINE_END); |
// writer.append("Content-Type: ")
|
||||||
writer.append("Content-Disposition: form-data; name=\"") |
// .append(URLConnection.guessContentTypeFromName(getEntity().getFileName()))
|
||||||
.append(attachment) |
// .append(LINE_END);
|
||||||
.append("\"; filename=\"") |
// writer.append("Content-Transfer-Encoding: binary").append(LINE_END);
|
||||||
.append(getEntity().getFileName()) |
// writer.append(LINE_END);
|
||||||
.append("\"") |
// writer.flush();
|
||||||
.append(LINE_END); |
//
|
||||||
writer.append("Content-Type: ") |
// FileInputStream inputStream = new FileInputStream(uploadFile);
|
||||||
.append(URLConnection.guessContentTypeFromName(getEntity().getFileName())) |
// byte[] buffer = new byte[4096];
|
||||||
.append(LINE_END); |
// int bytesLen;
|
||||||
writer.append("Content-Transfer-Encoding: binary").append(LINE_END); |
// while ((bytesLen = inputStream.read(buffer)) != -1) {
|
||||||
writer.append(LINE_END); |
// mOutputStream.write(buffer, 0, bytesLen);
|
||||||
writer.flush(); |
// progress(bytesLen);
|
||||||
|
// if (getThreadTask().isBreak()) {
|
||||||
FileInputStream inputStream = new FileInputStream(uploadFile); |
// break;
|
||||||
byte[] buffer = new byte[4096]; |
// }
|
||||||
int bytesLen; |
// if (mSpeedBandUtil != null) {
|
||||||
while ((bytesLen = inputStream.read(buffer)) != -1) { |
// mSpeedBandUtil.limitNextBytes(bytesLen);
|
||||||
mOutputStream.write(buffer, 0, bytesLen); |
// }
|
||||||
progress(bytesLen); |
// }
|
||||||
if (getThreadTask().isBreak()) { |
//
|
||||||
break; |
// mOutputStream.flush();
|
||||||
} |
// inputStream.close();
|
||||||
if (mSpeedBandUtil != null) { |
// writer.append(LINE_END).flush();
|
||||||
mSpeedBandUtil.limitNextBytes(bytesLen); |
// // 保证上传的文件和本地的一致,https://www.cnblogs.com/tugenhua0707/p/8975121.html
|
||||||
} |
// writer.append(PREFIX).append(BOUNDARY).append(PREFIX).append(LINE_END).flush();
|
||||||
} |
// }
|
||||||
|
//
|
||||||
mOutputStream.flush(); |
// /**
|
||||||
inputStream.close(); |
// * 任务结束操作
|
||||||
writer.append(LINE_END).flush(); |
// *
|
||||||
// 保证上传的文件和本地的一致,https://www.cnblogs.com/tugenhua0707/p/8975121.html
|
// * @throws IOException
|
||||||
writer.append(PREFIX).append(BOUNDARY).append(PREFIX).append(LINE_END).flush(); |
// */
|
||||||
} |
// private String finish(PrintWriter writer) throws IOException {
|
||||||
|
// StringBuilder response = new StringBuilder();
|
||||||
/** |
// int status = mHttpConn.getResponseCode();
|
||||||
* 任务结束操作 |
//
|
||||||
* |
// if (status == HttpURLConnection.HTTP_OK) {
|
||||||
* @throws IOException |
// BufferedReader reader =
|
||||||
*/ |
// new BufferedReader(new InputStreamReader(ConnectionHelp.convertInputStream(mHttpConn)));
|
||||||
private String finish(PrintWriter writer) throws IOException { |
// String line;
|
||||||
StringBuilder response = new StringBuilder(); |
// while (getThreadTask().isLive() && (line = reader.readLine()) != null) {
|
||||||
int status = mHttpConn.getResponseCode(); |
// response.append(line);
|
||||||
|
// }
|
||||||
if (status == HttpURLConnection.HTTP_OK) { |
// reader.close();
|
||||||
BufferedReader reader = |
// mHttpConn.disconnect();
|
||||||
new BufferedReader(new InputStreamReader(ConnectionHelp.convertInputStream(mHttpConn))); |
// getEntity().setResponseStr(response.toString());
|
||||||
String line; |
// complete();
|
||||||
while (getThreadTask().isLive() && (line = reader.readLine()) != null) { |
// } else {
|
||||||
response.append(line); |
// String msg = "response msg: " + mHttpConn.getResponseMessage() + ",code: " + status;
|
||||||
} |
// ALog.e(TAG, msg);
|
||||||
reader.close(); |
// getEntity().setResponseStr(response.toString());
|
||||||
mHttpConn.disconnect(); |
// fail(new AriaHTTPException(msg), false);
|
||||||
getEntity().setResponseStr(response.toString()); |
// response.append(status);
|
||||||
complete(); |
// }
|
||||||
} else { |
// writer.flush();
|
||||||
String msg = "response msg: " + mHttpConn.getResponseMessage() + ",code: " + status; |
// writer.close();
|
||||||
ALog.e(TAG, msg); |
// mOutputStream.close();
|
||||||
getEntity().setResponseStr(response.toString()); |
// return response.toString();
|
||||||
fail(new AriaHTTPException(msg), false); |
// }
|
||||||
response.append(status); |
//
|
||||||
} |
// @Override protected UploadEntity getEntity() {
|
||||||
writer.flush(); |
// return (UploadEntity) super.getEntity();
|
||||||
writer.close(); |
// }
|
||||||
mOutputStream.close(); |
//}
|
||||||
return response.toString(); |
|
||||||
} |
|
||||||
|
|
||||||
@Override protected UploadEntity getEntity() { |
|
||||||
return (UploadEntity) super.getEntity(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
@ -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); |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue