修复ftp服务器无法响应abor命令导致的无法停止上传的问题

修复ftp上传时,服务器有长度为0的文件导致上传失败的问题
修复下载任务和上传任务的文件路径是同一个时,导致的记录混乱问题
This commit is contained in:
laoyuyu
2019-12-17 22:04:21 +08:00
parent 0d93953cd9
commit 27c889e171
43 changed files with 295 additions and 145 deletions

View File

@@ -15,6 +15,7 @@
*/
package com.arialyy.aria.core;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.annotation.Ignore;
import com.arialyy.aria.orm.annotation.NoNull;
@@ -26,9 +27,9 @@ import java.util.List;
* 任务上传或下载的任务记录
*/
public class TaskRecord extends DbEntity {
public static final int TYPE_HTTP_FTP = 0;
public static final int TYPE_M3U8_VOD = 1;
public static final int TYPE_M3U8_LIVE = 2;
//public static final int TYPE_HTTP_FTP = 0;
//public static final int TYPE_M3U8_VOD = 1;
//public static final int TYPE_M3U8_LIVE = 2;
@Ignore
public List<ThreadRecord> threadRecords;
@@ -41,7 +42,6 @@ public class TaskRecord extends DbEntity {
/**
* 任务文件路径
*/
@Unique
public String filePath;
/**
@@ -79,8 +79,8 @@ public class TaskRecord extends DbEntity {
public boolean isBlock = false;
/**
* 线程类型
* {@link #TYPE_HTTP_FTP}、{@link #TYPE_M3U8_VOD}
* 任务类型
* {@link ITaskWrapper}
*/
public int taskType = 0;

View File

@@ -15,6 +15,7 @@
*/
package com.arialyy.aria.core;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
/**
@@ -56,7 +57,7 @@ public class ThreadRecord extends DbEntity {
/**
* 线程类型
* {@link TaskRecord#TYPE_HTTP_FTP}、{@link TaskRecord#TYPE_M3U8_VOD}
* {@link ITaskWrapper}
*/
public int threadType = 0;

View File

@@ -17,6 +17,7 @@ package com.arialyy.aria.core.common;
import android.os.Parcel;
import android.os.Parcelable;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.annotation.Default;
/**
@@ -44,6 +45,20 @@ public abstract class AbsNormalEntity extends AbsEntity implements Parcelable {
private boolean isRedirect = false; //是否重定向
private String redirectUrl; //重定向链接
/**
* 任务类型
* {@link ITaskWrapper}
*/
private int taskType;
@Override public int getTaskType() {
return taskType;
}
public void setTaskType(int taskType) {
this.taskType = taskType;
}
public String getUrl() {
return url;
}

View File

@@ -71,9 +71,11 @@ public class RecordHandler implements IRecordHandler {
convertDb();
} else {
mAdapter.onPre();
mTaskRecord = DbDataHelper.getTaskRecord(getFilePath());
mTaskRecord = DbDataHelper.getTaskRecord(getFilePath(), mEntity.getTaskType());
if (mTaskRecord == null) {
FileUtil.createFile(getFilePath());
if (!new File(getFilePath()).exists()){
FileUtil.createFile(getFilePath());
}
initRecord(true);
} else {
File file = new File(mTaskRecord.filePath);

View File

@@ -78,22 +78,22 @@ public class DownloadEntity extends AbsNormalEntity implements Parcelable {
return getUrl();
}
@Override public int getTaskType() {
int type;
if (TextUtils.isEmpty(getUrl())) {
type = ITaskWrapper.ERROR;
} else if (getUrl().startsWith("ftp")) {
type = ITaskWrapper.D_FTP;
} else {
M3U8Entity temp = getM3U8Entity();
if (temp == null) {
type = ITaskWrapper.D_HTTP;
} else {
type = temp.isLive() ? ITaskWrapper.M3U8_LIVE : ITaskWrapper.M3U8_VOD;
}
}
return type;
}
//@Override public int getTaskType() {
// int type;
// if (TextUtils.isEmpty(getUrl())) {
// type = ITaskWrapper.ERROR;
// } else if (getUrl().startsWith("ftp")) {
// type = ITaskWrapper.D_FTP;
// } else {
// M3U8Entity temp = getM3U8Entity();
// if (temp == null) {
// type = ITaskWrapper.D_HTTP;
// } else {
// type = temp.isLive() ? ITaskWrapper.M3U8_LIVE : ITaskWrapper.M3U8_VOD;
// }
// }
// return type;
//}
public DownloadEntity() {
}

View File

@@ -20,6 +20,7 @@ import android.os.Parcelable;
import android.text.TextUtils;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
import com.arialyy.aria.orm.annotation.Default;
import com.arialyy.aria.util.ALog;
@@ -153,7 +154,8 @@ public class M3U8Entity extends DbEntity implements Parcelable {
return null;
}
List<PeerInfo> peers = new ArrayList<>();
TaskRecord taskRecord = DbDataHelper.getTaskRecord(filePath);
TaskRecord taskRecord = DbDataHelper.getTaskRecord(filePath,
isLive ? ITaskWrapper.M3U8_LIVE : ITaskWrapper.M3U8_VOD);
File cacheDir = new File(getCacheDir());
if ((taskRecord == null
|| taskRecord.threadRecords == null

View File

@@ -17,9 +17,7 @@ package com.arialyy.aria.core.upload;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
import com.arialyy.aria.core.common.AbsNormalEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.annotation.Primary;
/**
@@ -58,12 +56,12 @@ public class UploadEntity extends AbsNormalEntity implements Parcelable {
return filePath;
}
@Override public int getTaskType() {
if (TextUtils.isEmpty(getUrl())){
return ITaskWrapper.ERROR;
}
return getUrl().startsWith("ftp") ? ITaskWrapper.U_FTP : ITaskWrapper.U_HTTP;
}
//@Override public int getTaskType() {
// if (TextUtils.isEmpty(getUrl())){
// return ITaskWrapper.ERROR;
// }
// return getUrl().startsWith("ftp") ? ITaskWrapper.U_FTP : ITaskWrapper.U_HTTP;
//}
public UploadEntity() {
}

View File

@@ -28,16 +28,7 @@ import java.net.URLEncoder;
abstract class AbsDelegate {
static final String TAG = "AbsDelegate";
/**
* URL编码字符串
*
* @param str 原始字符串
* @return 编码后的字符串
*/
String encodeStr(String str) {
str = str.replaceAll("\\\\+", "%2B");
return URLEncoder.encode(str);
}
/**
* 检查list参数是否合法list只能是{@code List<String>}

View File

@@ -34,7 +34,7 @@ class DBConfig {
static boolean DEBUG = false;
static Map<String, Class<? extends DbEntity>> mapping = new LinkedHashMap<>();
static String DB_NAME;
static int VERSION = 56;
static int VERSION = 57;
/**
* 是否将数据库保存在Sd卡{@code true} 是

View File

@@ -113,7 +113,7 @@ class DelegateCommon extends AbsDelegate {
sql = sql.replace("?", "%s");
Object[] params = new String[expression.length - 1];
for (int i = 0, len = params.length; i < len; i++) {
params[i] = String.format("'%s'", encodeStr(expression[i + 1]));
params[i] = String.format("'%s'", SqlUtil.encodeStr(expression[i + 1]));
}
sql = String.format(sql, params);
Cursor cursor = db.rawQuery(sql, null);

View File

@@ -205,7 +205,7 @@ class DelegateFind extends AbsDelegate {
sql = sql.replace("?", "%s");
Object[] params = new String[expression.length - 1];
for (int i = 0, len = params.length; i < len; i++) {
params[i] = String.format("'%s'", encodeStr(expression[i + 1]));
params[i] = String.format("'%s'", SqlUtil.encodeStr(expression[i + 1]));
}
sql = String.format(sql, params);
} else {
@@ -421,7 +421,7 @@ class DelegateFind extends AbsDelegate {
String[] temp = new String[selectionArgs.length];
int i = 0;
for (String arg : selectionArgs) {
temp[i] = encodeStr(arg);
temp[i] = SqlUtil.encodeStr(arg);
i++;
}
Cursor cursor = db.rawQuery(sql, temp);

View File

@@ -47,7 +47,7 @@ class DelegateUpdate extends AbsDelegate {
sql = sql.replace("?", "%s");
Object[] params = new String[expression.length - 1];
for (int i = 0, len = params.length; i < len; i++) {
params[i] = String.format("'%s'", encodeStr(expression[i + 1]));
params[i] = String.format("'%s'", SqlUtil.encodeStr(expression[i + 1]));
}
sql = String.format(sql, params);
db.execSQL(sql);
@@ -166,7 +166,7 @@ class DelegateUpdate extends AbsDelegate {
value = field.get(dbEntity).toString();
}
}
values.put(field.getName(), encodeStr(value));
values.put(field.getName(), SqlUtil.encodeStr(value));
}
return values;
} catch (IllegalAccessException e) {

View File

@@ -21,6 +21,9 @@ import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Build;
import android.text.TextUtils;
import com.arialyy.aria.core.download.M3U8Entity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.util.ALog;
import java.io.File;
import java.util.ArrayList;
@@ -102,6 +105,10 @@ final class SqlHelper extends SQLiteOpenHelper {
} else {
handleDbUpdate(db, null);
}
// 处理380版本TaskRecord 增加的记录类型判断
if (newVersion == 57) {
addTaskRecordType(db);
}
}
}
@@ -256,6 +263,79 @@ final class SqlHelper extends SQLiteOpenHelper {
return temp;
}
/**
* 给TaskRecord 增加任务类型
*/
private void addTaskRecordType(SQLiteDatabase db) {
try {
db.beginTransaction();
/*
* 增加下载实体的类型
*/
String dSql = "SELECT downloadPath, url FROM DownloadEntity";
Cursor c = db.rawQuery(dSql, null);
while (c.moveToNext()) {
int type;
String filePath = c.getString(0);
String url = c.getString(1);
if (url.startsWith("ftp") || url.startsWith("sftp")) {
type = ITaskWrapper.D_FTP;
} else {
if (mDelegate.tableExists(db, M3U8Entity.class)) {
Cursor m3u8c = db.rawQuery("SELECT isLive FROM M3U8Entity WHERE filePath=\""
+ SqlUtil.encodeStr(filePath)
+ "\"", null);
if (m3u8c.moveToNext()) {
String temp = m3u8c.getString(0);
type =
(TextUtils.isEmpty(temp) ? false : Boolean.valueOf(temp)) ? ITaskWrapper.M3U8_LIVE
: ITaskWrapper.M3U8_VOD;
} else {
type = ITaskWrapper.D_HTTP;
}
m3u8c.close();
} else {
type = ITaskWrapper.D_HTTP;
}
}
db.execSQL("UPDATE DownloadEntity SET taskType=? WHERE downloadPath=?",
new Object[] { type, filePath });
db.execSQL("UPDATE TaskRecord SET taskType=? WHERE filePath=?",
new Object[] { type, filePath });
db.execSQL("UPDATE ThreadRecord SET threadType=? WHERE taskKey=?",
new Object[] { type, filePath });
}
c.close();
/*
* 增加上传实体的类型
*/
String uSql = "SELECT filePath, url FROM UploadEntity";
c = db.rawQuery(uSql, null);
while (c.moveToNext()) {
int type;
String filePath = c.getString(c.getColumnIndex("filePath"));
String url = c.getString(c.getColumnIndex("url"));
if (url.startsWith("ftp") || url.startsWith("sftp")) {
type = ITaskWrapper.D_FTP;
} else {
type = ITaskWrapper.D_HTTP;
}
db.execSQL("UPDATE UploadEntity SET taskType=? WHERE filePath=?",
new Object[] { type, filePath });
db.execSQL("UPDATE TaskRecord SET taskType=? WHERE filePath=?",
new Object[] { type, filePath });
db.execSQL("UPDATE ThreadRecord SET threadType=? WHERE taskKey=?",
new Object[] { type, filePath });
}
c.close();
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
/**
* 删除重复的repeat数据
*/

View File

@@ -29,6 +29,7 @@ import com.arialyy.aria.orm.annotation.Wrapper;
import com.arialyy.aria.util.CommonUtil;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -41,6 +42,17 @@ import java.util.Set;
*/
final class SqlUtil {
/**
* URL编码字符串
*
* @param str 原始字符串
* @return 编码后的字符串
*/
static String encodeStr(String str) {
str = str.replaceAll("\\\\+", "%2B");
return URLEncoder.encode(str);
}
/**
* 获取主键字段名
*/

View File

@@ -141,8 +141,15 @@ public class CheckUtil {
*/
public static void checkMemberClass(Class clazz) {
int modifiers = clazz.getModifiers();
if (!clazz.isMemberClass() || !Modifier.isStatic(modifiers) || Modifier.isPrivate(modifiers)) {
ALog.e(TAG, "为了防止内存泄漏,请使用静态的成员类(public static class xxx)或文件类(A.java)");
//ALog.d(TAG, "isMemberClass = "
// + clazz.isMemberClass()
// + "; isStatic = "
// + Modifier.isStatic(modifiers)
// + "; isPrivate = "
// + Modifier.isPrivate(modifiers));
if (!clazz.isMemberClass() || !Modifier.isStatic(modifiers)) {
ALog.e(TAG, String.format("为了防止内存泄漏,请使用静态的成员类(public static class %s)或文件类(%s.java)",
clazz.getSimpleName(), clazz.getSimpleName()));
}
}

View File

@@ -15,12 +15,13 @@
*/
package com.arialyy.aria.util;
import com.arialyy.aria.core.wrapper.RecordWrapper;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.download.DGEntityWrapper;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.orm.DbEntity;
import java.io.File;
import java.util.ArrayList;
@@ -35,15 +36,20 @@ public class DbDataHelper {
* 获取任务记录
*
* @param filePath 文件地址
* @param taskType 任务类型{@link ITaskWrapper}
* @return 没有记录返回null有记录则返回任务记录
*/
public static TaskRecord getTaskRecord(String filePath) {
List<RecordWrapper> record =
DbEntity.findRelationData(RecordWrapper.class, "TaskRecord.filePath=?", filePath);
if (record == null || record.size() == 0) {
return null;
public static TaskRecord getTaskRecord(String filePath, int taskType) {
TaskRecord taskRecord =
DbEntity.findFirst(TaskRecord.class, "filePath=? AND taskType=?", filePath,
String.valueOf(taskType));
if (taskRecord != null) {
taskRecord.threadRecords =
DbEntity.findDatas(ThreadRecord.class, "taskKey=? AND threadType=?", filePath,
String.valueOf(taskType));
}
return record.get(0).taskRecord;
return taskRecord;
}
/**

View File

@@ -25,6 +25,7 @@ import com.arialyy.aria.core.download.DownloadGroupEntity;
import com.arialyy.aria.core.download.M3U8Entity;
import com.arialyy.aria.core.inf.IRecordHandler;
import com.arialyy.aria.core.upload.UploadEntity;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.core.wrapper.RecordWrapper;
import com.arialyy.aria.orm.DbEntity;
import java.io.File;
@@ -187,7 +188,7 @@ public class RecordUtil {
* @return true 为m3u8任务
*/
private static boolean recordIsM3U8(int recordType) {
return recordType == TaskRecord.TYPE_M3U8_VOD || recordType == TaskRecord.TYPE_M3U8_LIVE;
return recordType == ITaskWrapper.M3U8_VOD || recordType == ITaskWrapper.M3U8_LIVE;
}
/**
@@ -361,13 +362,14 @@ public class RecordUtil {
*
* @param oldPath 旧的文件路径
* @param newPath 新的文件路径
* @param taskType 任务类型{@link ITaskWrapper}
*/
public static void modifyTaskRecord(String oldPath, String newPath) {
public static void modifyTaskRecord(String oldPath, String newPath, int taskType) {
if (oldPath.equals(newPath)) {
ALog.w(TAG, "修改任务记录失败,新文件路径和旧文件路径一致");
return;
}
TaskRecord record = DbDataHelper.getTaskRecord(oldPath);
TaskRecord record = DbDataHelper.getTaskRecord(oldPath, taskType);
if (record == null) {
if (new File(oldPath).exists()) {
ALog.w(TAG, "修改任务记录失败,文件【" + oldPath + "】对应的任务记录不存在");