修复某些服务器range 返回不了长度的bug

Change-Id: I4a239898bdf0926c6ef2ad58e3fde51e06dd597d
pull/330/head
laoyuyu 7 years ago
parent 50ed36a470
commit 402086d7dd
  1. 16
      Aria/src/main/java/com/arialyy/aria/core/delegate/FtpDelegate.java
  2. 35
      Aria/src/main/java/com/arialyy/aria/core/delegate/HttpHeaderDelegate.java
  3. 2
      Aria/src/main/java/com/arialyy/aria/core/download/DownloadTarget.java
  4. 2
      Aria/src/main/java/com/arialyy/aria/core/download/FtpDirDownloadTarget.java
  5. 2
      Aria/src/main/java/com/arialyy/aria/core/download/FtpDownloadTarget.java
  6. 45
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/ConnectionHelp.java
  7. 34
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpFileInfoThread.java
  8. 59
      Aria/src/main/java/com/arialyy/aria/core/download/downloader/HttpThreadTask.java
  9. 1
      Aria/src/main/java/com/arialyy/aria/core/inf/ITarget.java
  10. 4
      Aria/src/main/java/com/arialyy/aria/core/upload/FtpUploadTarget.java
  11. 2
      Aria/src/main/java/com/arialyy/aria/core/upload/UploadTarget.java
  12. 3
      AriaFtpPlug/src/main/java/org/apache/commons/net/ftp/parser/MacOsPeterFTPEntryParser.java
  13. 1
      DEV_LOG.md
  14. 4
      app/src/main/assets/aria_config.xml
  15. 8
      app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java

@ -31,16 +31,18 @@ public class FtpDelegate<TARGET extends ITarget, ENTITY extends AbsEntity, TASK_
private static final String TAG = "FtpDelegate";
private ENTITY mEntity;
private TASK_ENTITY mTaskEntity;
private TARGET mTarget;
public FtpDelegate(TASK_ENTITY mTaskEntity) {
this.mTaskEntity = mTaskEntity;
public FtpDelegate(TARGET target, TASK_ENTITY taskEntity) {
mTarget = target;
mTaskEntity = taskEntity;
mEntity = mTaskEntity.getEntity();
}
@Override public TARGET charSet(String charSet) {
if (TextUtils.isEmpty(charSet)) return (TARGET) this;
if (TextUtils.isEmpty(charSet)) return mTarget;
mTaskEntity.charSet = charSet;
return (TARGET) this;
return mTarget;
}
@Override public TARGET login(String userName, String password) {
@ -50,15 +52,15 @@ public class FtpDelegate<TARGET extends ITarget, ENTITY extends AbsEntity, TASK_
@Override public TARGET login(String userName, String password, String account) {
if (TextUtils.isEmpty(userName)) {
ALog.e(TAG, "用户名不能为null");
return (TARGET) this;
return mTarget;
} else if (TextUtils.isEmpty(password)) {
ALog.e(TAG, "密码不能为null");
return (TARGET) this;
return mTarget;
}
mTaskEntity.urlEntity.needLogin = true;
mTaskEntity.urlEntity.user = userName;
mTaskEntity.urlEntity.password = password;
mTaskEntity.urlEntity.account = account;
return (TARGET) this;
return mTarget;
}
}

@ -37,9 +37,12 @@ public class HttpHeaderDelegate<TARGET extends ITarget, ENTITY extends AbsEntity
private static final String TAG = "HttpHeaderDelegate";
private ENTITY mEntity;
private TASK_ENTITY mTaskEntity;
private TARGET mTarget;
public HttpHeaderDelegate(TARGET target, TASK_ENTITY taskEntity) {
mTarget = target;
mTaskEntity = taskEntity;
public HttpHeaderDelegate(TASK_ENTITY mTaskEntity) {
this.mTaskEntity = mTaskEntity;
mEntity = mTaskEntity.getEntity();
}
@ -54,10 +57,10 @@ public class HttpHeaderDelegate<TARGET extends ITarget, ENTITY extends AbsEntity
public TARGET addHeader(@NonNull String key, @NonNull String value) {
if (TextUtils.isEmpty(key)) {
ALog.w(TAG, "设置header失败,header对应的key不能为null");
return (TARGET) this;
return mTarget;
} else if (TextUtils.isEmpty(value)) {
ALog.w(TAG, "设置header失败,header对应的value不能为null");
return (TARGET) this;
return mTarget;
}
if (mTaskEntity.headers.get(key) == null) {
mTaskEntity.headers.put(key, value);
@ -66,7 +69,7 @@ public class HttpHeaderDelegate<TARGET extends ITarget, ENTITY extends AbsEntity
mTaskEntity.headers.put(key, value);
mTaskEntity.update();
}
return (TARGET) this;
return mTarget;
}
/**
@ -79,7 +82,7 @@ public class HttpHeaderDelegate<TARGET extends ITarget, ENTITY extends AbsEntity
public TARGET addHeaders(@NonNull Map<String, String> headers) {
if (headers.size() == 0) {
ALog.w(TAG, "设置header失败,map没有header数据");
return (TARGET) this;
return mTarget;
}
/*
两个map比较逻辑
@ -123,7 +126,7 @@ public class HttpHeaderDelegate<TARGET extends ITarget, ENTITY extends AbsEntity
mTaskEntity.update();
}
return (TARGET) this;
return mTarget;
}
/**
@ -135,7 +138,7 @@ public class HttpHeaderDelegate<TARGET extends ITarget, ENTITY extends AbsEntity
@Override
public TARGET setRequestMode(RequestEnum requestEnum) {
mTaskEntity.requestEnum = requestEnum;
return (TARGET) this;
return mTarget;
}
/**
@ -145,12 +148,12 @@ public class HttpHeaderDelegate<TARGET extends ITarget, ENTITY extends AbsEntity
*/
@Override
public TARGET setHeaderMd5Key(String md5Key) {
if (TextUtils.isEmpty(md5Key)) return (TARGET) this;
if (TextUtils.isEmpty(md5Key)) return mTarget;
mTaskEntity.md5Key = md5Key;
if (TextUtils.isEmpty(mTaskEntity.md5Key) || !mTaskEntity.md5Key.equals(md5Key)) {
mTaskEntity.update();
}
return (TARGET) this;
return mTarget;
}
/**
@ -159,13 +162,13 @@ public class HttpHeaderDelegate<TARGET extends ITarget, ENTITY extends AbsEntity
*/
@Override
public TARGET setHeaderContentLengthKey(String contentLength) {
if (TextUtils.isEmpty(contentLength)) return (TARGET) this;
if (TextUtils.isEmpty(contentLength)) return mTarget;
mTaskEntity.contentLength = contentLength;
if (TextUtils.isEmpty(mTaskEntity.contentLength) || !mTaskEntity.contentLength.equals(
contentLength)) {
mTaskEntity.update();
}
return (TARGET) this;
return mTarget;
}
/**
@ -175,13 +178,13 @@ public class HttpHeaderDelegate<TARGET extends ITarget, ENTITY extends AbsEntity
*/
@Override
public TARGET setHeaderDispositionKey(String dispositionKey) {
if (TextUtils.isEmpty(dispositionKey)) return (TARGET) this;
if (TextUtils.isEmpty(dispositionKey)) return mTarget;
mTaskEntity.dispositionKey = dispositionKey;
if (TextUtils.isEmpty(mTaskEntity.dispositionKey) || !mTaskEntity.dispositionKey.equals(
dispositionKey)) {
mTaskEntity.update();
}
return (TARGET) this;
return mTarget;
}
/**
@ -191,12 +194,12 @@ public class HttpHeaderDelegate<TARGET extends ITarget, ENTITY extends AbsEntity
*/
@Override
public TARGET setHeaderDispositionFileKey(String dispositionFileKey) {
if (TextUtils.isEmpty(dispositionFileKey)) return (TARGET) this;
if (TextUtils.isEmpty(dispositionFileKey)) return mTarget;
mTaskEntity.dispositionFileKey = dispositionFileKey;
if (TextUtils.isEmpty(mTaskEntity.dispositionFileKey) || !mTaskEntity.dispositionFileKey.equals(
dispositionFileKey)) {
mTaskEntity.update();
}
return (TARGET) this;
return mTarget;
}
}

@ -49,7 +49,7 @@ public class DownloadTarget extends BaseNormalTarget<DownloadTarget>
}
private void initTHis() {
mDelegate = new HttpHeaderDelegate<>(mTaskEntity);
mDelegate = new HttpHeaderDelegate<>(this, mTaskEntity);
}
/**

@ -45,7 +45,7 @@ public class FtpDirDownloadTarget extends BaseGroupTarget<FtpDirDownloadTarget>
mTaskEntity.requestType = AbsTaskEntity.D_FTP_DIR;
mEntity = mTaskEntity.entity;
mDelegate = new FtpDelegate<>(mTaskEntity);
mDelegate = new FtpDelegate<>(this, mTaskEntity);
}
@Override protected int getTargetType() {

@ -51,7 +51,7 @@ public class FtpDownloadTarget extends BaseNormalTarget<FtpDownloadTarget>
mTaskEntity.refreshInfo = refreshInfo;
mTaskEntity.requestType = AbsTaskEntity.D_FTP;
mDelegate = new FtpDelegate<>(mTaskEntity);
mDelegate = new FtpDelegate<>(this, mTaskEntity);
}
/**

@ -15,6 +15,7 @@
*/
package com.arialyy.aria.core.download.downloader;
import android.util.Log;
import com.arialyy.aria.core.download.DownloadTaskEntity;
import com.arialyy.aria.util.SSLContextUtil;
import java.io.IOException;
@ -80,28 +81,28 @@ class ConnectionHelp {
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 (keys == null || !keys.contains("Accept")) {
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("text/plain, ")
.append("text/html, ")
.append("*/*");
conn.setRequestProperty("Accept", accept.toString());
}
//if (keys == null || !keys.contains("Accept")) {
// 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("text/plain, ")
// .append("text/html, ")
// .append("*/*");
// conn.setRequestProperty("Accept", accept.toString());
//}
if (keys == null || !keys.contains("Accept-Encoding")) {
conn.setRequestProperty("Accept-Encoding", "identity");
}

@ -15,7 +15,9 @@
*/
package com.arialyy.aria.core.download.downloader;
import android.location.Address;
import android.text.TextUtils;
import android.util.Log;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.common.CompleteInfo;
import com.arialyy.aria.core.common.OnFileInfoCallback;
@ -27,7 +29,9 @@ import com.arialyy.aria.util.CommonUtil;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.InetAddress;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.List;
import java.util.Map;
@ -58,10 +62,7 @@ class HttpFileInfoThread implements Runnable {
conn = ConnectionHelp.setConnectParam(mTaskEntity, conn);
conn.setRequestProperty("Range", "bytes=" + 0 + "-");
conn.setConnectTimeout(mConnectTimeOut);
conn.setRequestMethod(mTaskEntity.requestEnum.name);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setChunkedStreamingMode(0);
//conn.setChunkedStreamingMode(0);
conn.connect();
handleConnect(conn);
} catch (IOException e) {
@ -83,6 +84,17 @@ class HttpFileInfoThread implements Runnable {
if (len < 0) {
String temp = conn.getHeaderField(mTaskEntity.contentLength);
len = TextUtils.isEmpty(temp) ? -1 : Long.parseLong(temp);
// 某些服务,如果设置了conn.setRequestProperty("Range", "bytes=" + 0 + "-");
// 会返回 Content-Range: bytes 0-225427911/225427913
if (len < 0){
temp = conn.getHeaderField("Content-Range");
if (TextUtils.isEmpty(temp)){
len = -1;
}else {
int start = temp.indexOf("/");
len = Long.parseLong(temp.substring(start + 1, temp.length()));
}
}
}
int code = conn.getResponseCode();
boolean isComplete = false;
@ -90,20 +102,22 @@ class HttpFileInfoThread implements Runnable {
String md5Code = conn.getHeaderField(mTaskEntity.md5Key);
mEntity.setMd5Code(md5Code);
}
String disposition = conn.getHeaderField(mTaskEntity.dispositionKey);
Map<String, List<String>> headers = conn.getHeaderFields();
boolean isChunked = false;
//https://my.oschina.net/ososchina/blog/666761
if (conn.getHeaderField("Transfer-Encoding").equals("chunked")) {
final String str = conn.getHeaderField("Transfer-Encoding");
if (!TextUtils.isEmpty(str) && str.equals("chunked")) {
isChunked = true;
StringBuffer sb = new StringBuffer();
byte[] buffer = new byte[1024];
InputStream is = conn.getInputStream();
int l = 0;
//StringBuffer sb = new StringBuffer();
//byte[] buffer = new byte[1024];
//InputStream is = conn.getInputStream();
//int l = 0;
//while (true){
// is.read()
//}
}
String disposition = conn.getHeaderField(mTaskEntity.dispositionKey);
if (!TextUtils.isEmpty(disposition)) {
mEntity.setDisposition(CommonUtil.encryptBASE64(disposition));
if (disposition.contains(mTaskEntity.dispositionFileKey)) {

@ -90,28 +90,7 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
if (STATE.isCancel || STATE.isStop) {
return;
}
//支持断点的处理
if (mConfig.SUPPORT_BP) {
ALog.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】线程__" + mConfig.THREAD_ID + "__下载完毕");
writeConfig(true, 1);
STATE.COMPLETE_THREAD_NUM++;
if (STATE.isComplete()) {
File configFile = new File(mConfigFPath);
if (configFile.exists()) {
configFile.delete();
}
STATE.isRunning = false;
mListener.onComplete();
}
if (STATE.isFail()) {
STATE.isRunning = false;
mListener.onFail(false);
}
} else {
ALog.i(TAG, "任务下载完成");
STATE.isRunning = false;
mListener.onComplete();
}
handleStop();
} catch (MalformedURLException e) {
fail(mChildCurrentLocation, "下载链接异常", e);
} catch (IOException e) {
@ -140,7 +119,7 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
*/
private void readChunk(InputStream is, RandomAccessFile file)
throws IOException, InterruptedException {
}
/**
@ -162,6 +141,40 @@ final class HttpThreadTask extends AbsThreadTask<DownloadEntity, DownloadTaskEnt
}
}
/**
* 处理暂停或完成配置文件的更新或事件回调
*
* @throws IOException
*/
private void handleStop() throws IOException {
//支持断点的处理
if (mConfig.SUPPORT_BP) {
if (mChildCurrentLocation == mConfig.END_LOCATION) {
ALog.i(TAG, "任务【" + mConfig.TEMP_FILE.getName() + "】线程__" + mConfig.THREAD_ID + "__下载完毕");
writeConfig(true, 1);
STATE.COMPLETE_THREAD_NUM++;
if (STATE.isComplete()) {
File configFile = new File(mConfigFPath);
if (configFile.exists()) {
configFile.delete();
}
STATE.isRunning = false;
mListener.onComplete();
}
} else {
STATE.FAIL_NUM++;
}
if (STATE.isFail()) {
STATE.isRunning = false;
mListener.onFail(false);
}
} else {
ALog.i(TAG, "任务下载完成");
STATE.isRunning = false;
mListener.onComplete();
}
}
@Override protected String getTaskType() {
return "HTTP_DOWNLOAD";
}

@ -19,7 +19,6 @@ package com.arialyy.aria.core.inf;
* Created by AriaL on 2017/6/29.
*/
public interface ITarget<TARGET extends ITarget> {
/**
* 获取任务状态
*

@ -21,10 +21,8 @@ import com.arialyy.aria.core.command.normal.NormalCmdFactory;
import com.arialyy.aria.core.delegate.FtpDelegate;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import com.arialyy.aria.core.inf.IFtpTarget;
import com.arialyy.aria.core.manager.TEManager;
import com.arialyy.aria.util.CheckUtil;
import com.arialyy.aria.util.CommonUtil;
import java.io.File;
/**
* Created by Aria.Lao on 2017/7/27.
@ -43,7 +41,7 @@ public class FtpUploadTarget extends BaseNormalTarget<FtpUploadTarget>
private void initTask(String filePath) {
initTarget(filePath);
mTaskEntity.requestType = AbsTaskEntity.U_FTP;
mDelegate = new FtpDelegate<>(mTaskEntity);
mDelegate = new FtpDelegate<>(this, mTaskEntity);
}
/**

@ -43,7 +43,7 @@ public class UploadTarget extends BaseNormalTarget<UploadTarget>
//http暂时不支持断点上传
mTaskEntity.isSupportBP = false;
mTaskEntity.requestType = AbsTaskEntity.U_HTTP;
mDelegate = new HttpHeaderDelegate<>(mTaskEntity);
mDelegate = new HttpHeaderDelegate<>(this, mTaskEntity);
}
@Override public UploadTarget setUploadUrl(@NonNull String uploadUrl) {

@ -29,7 +29,8 @@ import org.apache.commons.net.ftp.FTPFile;
* @see org.apache.commons.net.ftp.FTPFileEntryParser FTPFileEntryParser (for usage instructions)
* @since 3.1
*/
public class MacOsPeterFTPEntryParser extends ConfigurableFTPFileEntryParserImpl {
public class
MacOsPeterFTPEntryParser extends ConfigurableFTPFileEntryParserImpl {
static final String DEFAULT_DATE_FORMAT = "MMM d yyyy"; //Nov 9 2001

@ -1,6 +1,7 @@
## 开发日志
+ v_3.3.16
- 修复一个activity启动多次,无法进行回掉的bug https://github.com/AriaLyy/Aria/issues/200
- 优化target代码结构
+ v_3.3.14
- 修复ftp上传和下载的兼容性问题
- 如果url中的path有"//"将替换为"/"

@ -5,13 +5,13 @@
<download>
<!--设置下载线程,线程下载数改变后,新的下载任务才会生效,如果任务大小小于1m,该设置也不会生效-->
<threadNum value="3"/>
<threadNum value="1"/>
<!--设置下载队列最大任务数, 默认为2-->
<maxTaskNum value="2"/>
<!--设置下载失败,重试次数,默认为10-->
<reTryNum value="2"/>
<reTryNum value="1"/>
<!--设置重试间隔,单位为毫秒,默认2000毫秒-->
<reTryInterval value="5000"/>

@ -29,6 +29,7 @@ import android.widget.Toast;
import butterknife.Bind;
import com.arialyy.annotations.Download;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.common.RequestEnum;
import com.arialyy.aria.core.download.DownloadTarget;
import com.arialyy.aria.core.download.DownloadTask;
import com.arialyy.aria.core.inf.IEntity;
@ -61,8 +62,9 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
//"http://qudao.5535.cn/one/game.html?game=531&cpsuser=xiaoeryu2";
//"https://bogoe-res.mytbz.com/tbzengsong/If You're Happy.mp3";
//"http://ozr0ucjs5.bkt.clouddn.com/51_box-104_20180131202610.apk";
"http://kf.lyfz.net/api/v1/we_chat/Business/getMaterial?company_id=51454009d703c86c91353f61011ecf2f&appid=wx88c6052d06eaaf7d&media_id=qpkQb72KqNkZhBNIUw7asF0LuJouXCTBd3A-rS2bYl7H4kvTZstEXD3F-pDVeqA-&type=3";
//"http://kf.lyfz.net/api/v1/we_chat/Business/getMaterial?company_id=51454009d703c86c91353f61011ecf2f&appid=wx88c6052d06eaaf7d&media_id=qpkQb72KqNkZhBNIUw7asF0LuJouXCTBd3A-rS2bYl7H4kvTZstEXD3F-pDVeqA-&type=3";
//"https://www.baidu.com/link?url=_LFCuTPtnzFxVJByJ504QymRywIA1Z_T5xUxe9ZLuxcGM0C_RcdpWyB1eGjbJC-e5wv5wAKM4WmLMAS5KeF6EZJHB8Va3YqZUiaErqK_pxm&wd=&eqid=e8583fe70002d126000000065a99f864";
"http://58.210.9.131/tpk/sipgt/TDLYZTGH.tpk";
@Bind(R.id.start) Button mStart;
@Bind(R.id.stop) Button mStop;
@Bind(R.id.cancel) Button mCancel;
@ -230,8 +232,8 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
.addHeader("Accept-Encoding", "gzip, deflate")
.addHeader("DNT", "1")
//.addHeader("Cookie", "BAIDUID=648E5FF020CC69E8DD6F492D1068AAA9:FG=1; BIDUPSID=648E5FF020CC69E8DD6F492D1068AAA9; PSTM=1519099573; BD_UPN=12314753; locale=zh; BDSVRTM=0")
//.setRequestMode(RequestEnum.POST)
.setDownloadPath(Environment.getExternalStorageDirectory().getPath() + "/ggsg1.apk")
.setRequestMode(RequestEnum.GET)
.setFilePath(Environment.getExternalStorageDirectory().getPath() + "/ggsg1.apk")
.resetState()
.start();
//.add();

Loading…
Cancel
Save