Get file name according to roc 6266

v4
laoyuyu 2 years ago
parent ef754f04cc
commit 1415de11c6
  1. 4
      Http/src/main/java/com/arialyy/aria/http/HttpUtil.kt
  2. 3
      Http/src/main/java/com/arialyy/aria/http/download/HttpBlockThreadInterceptor.kt
  3. 7
      Http/src/main/java/com/arialyy/aria/http/download/HttpDBlockInterceptor.kt
  4. 2
      Http/src/main/java/com/arialyy/aria/http/download/HttpDCheckInterceptor.kt
  5. 52
      Http/src/main/java/com/arialyy/aria/http/download/HttpDHeaderInterceptor.kt
  6. 2
      Http/src/main/java/com/arialyy/aria/http/download/HttpDOptionAdapter.kt
  7. 22
      Http/src/main/java/com/arialyy/aria/http/download/HttpDStartController.kt
  8. 2
      Http/src/main/java/com/arialyy/aria/http/download/HttpDStopController.kt
  9. 25
      Http/src/main/java/com/arialyy/aria/http/download/HttpDTaskAdapter.kt
  10. 130
      HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGCheckInterceptor.kt
  11. 23
      HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGStartController.kt
  12. 93
      HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGSubTaskInterceptor.kt
  13. 5
      HttpGroup/src/main/java/com/arialyy/dua/group/HttpDGroupAdapter.kt
  14. 2
      PublicComponent/src/main/java/com/arialyy/aria/core/inf/ITaskAdapter.java
  15. 8
      PublicComponent/src/main/java/com/arialyy/aria/core/task/DownloadGroupTask.java
  16. 39
      PublicComponent/src/main/java/com/arialyy/aria/core/task/TaskCachePool.kt
  17. 3
      PublicComponent/src/main/java/com/arialyy/aria/core/task/TaskResp.kt
  18. 8
      PublicComponent/src/main/java/com/arialyy/aria/orm/dao/DEntityDao.kt
  19. 8
      PublicComponent/src/main/java/com/arialyy/aria/orm/dao/DGEntityDao.kt
  20. 2
      PublicComponent/src/main/java/com/arialyy/aria/orm/dao/MEntityDao.kt
  21. 2
      PublicComponent/src/main/java/com/arialyy/aria/orm/dao/RecordDao.kt
  22. 6
      PublicComponent/src/main/java/com/arialyy/aria/orm/dao/UEntityDao.kt
  23. 15
      PublicComponent/src/main/java/com/arialyy/aria/orm/entity/DEntity.kt
  24. 37
      PublicComponent/src/main/java/com/arialyy/aria/util/DuaUtil.kt
  25. 5
      PublicComponent/src/main/java/com/arialyy/aria/util/Ext.kt
  26. 22
      PublicComponent/src/main/java/com/arialyy/aria/util/FileUtils.kt

@ -95,6 +95,10 @@ object HttpUtil {
Timber.e("invalid uri, ${option.savePathUri}")
return false
}
if (!FileUtils.uriIsDir(option.savePathUri!!)){
Timber.e("invalid uri, that path not a dir")
return false
}
return true
}
}

@ -17,7 +17,6 @@ package com.arialyy.aria.http.download
import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.inf.IBlockManager
import com.arialyy.aria.core.task.BlockManager
import com.arialyy.aria.core.task.ITaskInterceptor
import com.arialyy.aria.core.task.IThreadTask
import com.arialyy.aria.core.task.TaskChain
@ -39,7 +38,7 @@ class HttpBlockThreadInterceptor : ITaskInterceptor {
blockManager = chain.blockManager as IBlockManager
val unfinishedBlockList = blockManager.unfinishedBlockList
if (unfinishedBlockList.isEmpty()) {
return TaskResp(TaskResp.CODE_BLOCK_QUEUE_NULL)
return TaskResp(TaskResp.CODE_INTERRUPT)
}
createThreadTask(unfinishedBlockList, chain)
return TaskResp(TaskResp.CODE_SUCCESS)

@ -20,7 +20,6 @@ import com.arialyy.aria.core.inf.IBlockManager
import com.arialyy.aria.core.inf.ITaskManager
import com.arialyy.aria.core.task.ITask
import com.arialyy.aria.core.task.ITaskInterceptor
import com.arialyy.aria.core.task.TaskCachePool
import com.arialyy.aria.core.task.TaskChain
import com.arialyy.aria.core.task.TaskResp
import com.arialyy.aria.http.HttpTaskOption
@ -51,13 +50,13 @@ internal class HttpDBlockInterceptor : ITaskInterceptor {
option = task.getTaskOption(HttpTaskOption::class.java)
if (task.taskState.fileSize < 0) {
Timber.e("file size < 0")
return TaskResp(TaskResp.CODE_GET_FILE_INFO_FAIL)
return TaskResp(TaskResp.CODE_INTERRUPT)
}
val savePath = FileUri.getPathByUri(task.getTaskOption(HttpTaskOption::class.java).savePathUri)
if (savePath.isNullOrEmpty()) {
Timber.e("saveUri is null")
return TaskResp(TaskResp.CODE_SAVE_URI_NULL)
return TaskResp(TaskResp.CODE_INTERRUPT)
}
// if task not support resume, don't save record
@ -95,7 +94,7 @@ internal class HttpDBlockInterceptor : ITaskInterceptor {
*/
private suspend fun checkRecord(): Int {
val recordDao = DuaContext.getServiceManager().getDbService().getDuaDb().getRecordDao()
val recordWrapper = recordDao.getTaskRecordByKey(task.filePath)
val recordWrapper = recordDao.queryTaskRecordByKey(task.filePath)
if (recordWrapper == null) {
Timber.i("record not found, create record")

@ -36,7 +36,7 @@ class HttpDCheckInterceptor : ITaskInterceptor {
private suspend fun findDEntityBySavePath(option: HttpTaskOption): DEntity {
val savePath = option.savePathUri
val dao = DuaContext.getServiceManager().getDbService().getDuaDb().getDEntityDao()
val de = dao.getDEntityBySavePath(savePath.toString())
val de = dao.queryDEntityBySavePath(savePath.toString())
if (de != null) {
return de
}

@ -29,6 +29,8 @@ import com.arialyy.aria.http.HttpTaskOption
import com.arialyy.aria.http.HttpUtil
import com.arialyy.aria.http.request.IRequest
import com.arialyy.aria.orm.entity.BlockRecord
import com.arialyy.aria.orm.entity.DEntity
import com.arialyy.aria.util.DuaUtil
import com.arialyy.aria.util.FileUtils
import timber.log.Timber
import java.io.BufferedReader
@ -45,6 +47,7 @@ import java.util.UUID
internal class HttpDHeaderInterceptor : ITaskInterceptor {
private lateinit var task: ITask
private lateinit var taskOption: HttpTaskOption
private var disposition: String? = null
companion object {
private val CODE_30X = listOf(
@ -75,6 +78,12 @@ internal class HttpDHeaderInterceptor : ITaskInterceptor {
getOptionAdapter().isSupportResume = fileSize != 0L
getOptionAdapter().isSupportBlock =
getOptionAdapter().isSupportResume && fileSize > BlockRecord.BLOCK_SIZE
val fileName =
getFileName(if (taskOption.redirectUrl.isNullOrEmpty()) taskOption.sourUrl!! else taskOption.redirectUrl!!)
(task.taskState.entity as DEntity?)?.let {
it.fileName = fileName
it.update()
}
return chain.proceed(task)
}
} catch (e: IOException) {
@ -83,7 +92,7 @@ internal class HttpDHeaderInterceptor : ITaskInterceptor {
chain.getTask().getTaskOption(HttpTaskOption::class.java).sourUrl
}"
)
return TaskResp(TaskResp.CODE_GET_FILE_INFO_FAIL)
return TaskResp(TaskResp.CODE_INTERRUPT)
}
Timber.e("can't get fileSize")
return TaskResp(TaskResp.CODE_INTERRUPT)
@ -102,10 +111,51 @@ internal class HttpDHeaderInterceptor : ITaskInterceptor {
return handleConnect(conn)
}
/**
* get file name
* if already set file name, use it.
* if no file name set, will try to get the file name
*/
private fun getFileName(url: String): String {
if (getOptionAdapter().fileName?.isNotEmpty() == true) {
return getOptionAdapter().fileName!!
}
// step1, get file name from header
if (!disposition.isNullOrEmpty()) {
val tempName = getFileNameFromContentDisposition(disposition!!)
if (!tempName.isNullOrEmpty()) {
Timber.d("get file name from disposition")
return tempName
}
}
// step2. get file name from url
val fileName = FileUtils.getFileNameFromUrl(url)
if (!fileName.isNullOrEmpty()) {
Timber.d("get file name from url")
return fileName
}
// step3. get file name from md5
val md5Name = DuaUtil.getMD5Hash(url)
Timber.d("use the md5 code of the url to get the file name, $md5Name")
return md5Name
}
/**
* [RFC6266](https://httpwg.org/specs/rfc6266.html#rfc.section.4)
*/
private fun getFileNameFromContentDisposition(contentDisposition: String): String? {
val regex = Regex("filename=\"(.+?)\"")
val matchResult = regex.find(contentDisposition)
return matchResult?.groupValues?.getOrNull(1)
}
@Throws(IOException::class)
private fun handleConnect(conn: HttpURLConnection): Long {
val code = conn.responseCode
disposition = conn.getHeaderField("Content-Disposition")
when {
code == HttpURLConnection.HTTP_PARTIAL -> return getFileSizeFromHeader(conn.headerFields)
code == HttpURLConnection.HTTP_OK -> {

@ -39,4 +39,6 @@ class HttpDOptionAdapter : IHttpTaskOptionAdapter {
*/
var isSupportBlock = true
var fileName: String? = null
}

@ -37,11 +37,11 @@ import java.net.HttpURLConnection
* @Date 12:38 PM 2023/1/22
**/
class HttpDStartController(target: Any, val url: String) : HttpBaseStartController(target) {
private val taskOptionSupport = HttpDOptionAdapter()
private val taskOptionAdapter = HttpDOptionAdapter()
init {
httpTaskOption.sourUrl = url
httpTaskOption.taskOptionAdapter = taskOptionSupport
httpTaskOption.taskOptionAdapter = taskOptionAdapter
}
override fun setTaskInterceptor(taskInterceptor: ITaskInterceptor): HttpDStartController {
@ -60,7 +60,7 @@ class HttpDStartController(target: Any, val url: String) : HttpBaseStartControll
* Maybe the server has special rules, you need set [IHttpFileLenAdapter] to get the file length from [HttpURLConnection.getHeaderFields]
*/
fun setHttpFileLenAdapter(adapter: IHttpFileLenAdapter): HttpDStartController {
taskOptionSupport.fileSizeAdapter = adapter
taskOptionAdapter.fileSizeAdapter = adapter
return this
}
@ -73,7 +73,19 @@ class HttpDStartController(target: Any, val url: String) : HttpBaseStartControll
}
/**
* set file save path, eg: /mnt/sdcard/Downloads/test.zip
* set file name
*/
fun setFileName(fileName: String): HttpDStartController {
taskOptionAdapter.fileName = fileName
return this
}
/**
* set file save path, if you don't set the [setFileName],
* it will automatically try to get the file name, and if it fails,
* the md5 code of the url will be used
* eg: /mnt/sdcard/Downloads/
*
*/
fun setSavePath(savePath: Uri): HttpDStartController {
httpTaskOption.savePathUri = savePath
@ -84,7 +96,7 @@ class HttpDStartController(target: Any, val url: String) : HttpBaseStartControll
if (HttpUtil.checkHttpDParams(httpTaskOption)) {
throw IllegalArgumentException("invalid params")
}
val tempTask = TaskCachePool.getTaskByUrl(url)
val tempTask = TaskCachePool.getTaskByKey(url)
if (tempTask != null) {
return tempTask as DownloadTask
}

@ -56,7 +56,7 @@ class HttpDStopController(val taskId: Int) {
Timber.e("task not found, taskId: $taskId")
return
}
val util = TaskCachePool.getTaskAdapter(Uri.parse(task.filePath))
val util = task.adapter
if (util == null) {
Timber.e("resume fail, please restart task, taskId: $taskId")
return

@ -99,29 +99,4 @@ internal class HttpDTaskAdapter : AbsTaskAdapter() {
Looper.loop()
}
}
override fun resume() {
getTask().getTaskOption(HttpTaskOption::class.java).taskInterceptor.let {
if (it.isNotEmpty()) {
addInterceptors(it)
}
}
DuaContext.duaScope.launch(Dispatchers.IO) {
Looper.prepare()
blockManager?.setLooper()
addCoreInterceptor(TimerInterceptor())
addCoreInterceptor(HttpDBlockInterceptor())
addCoreInterceptor(HttpBlockThreadInterceptor())
val resp = interceptor()
if (resp == null || resp.code != TaskResp.CODE_SUCCESS) {
getTask().getTaskOption(HttpTaskOption::class.java).eventListener.onFail(
false,
AriaException("start task fail, task interrupt, code: ${resp?.code ?: TaskResp.CODE_INTERRUPT}")
)
blockManager?.stop()
return@launch
}
Looper.loop()
}
}
}

@ -15,11 +15,20 @@
*/
package com.arialyy.dua.group
import android.net.Uri
import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.task.ITask
import com.arialyy.aria.core.task.ITaskInterceptor
import com.arialyy.aria.core.task.TaskChain
import com.arialyy.aria.core.task.TaskResp
import com.arialyy.aria.http.HttpTaskOption
import com.arialyy.aria.orm.entity.DEntity
import com.arialyy.aria.orm.entity.DGEntity
import com.arialyy.aria.util.CheckUtil
import com.arialyy.aria.util.FileUri
import com.arialyy.aria.util.FileUtils
import timber.log.Timber
import java.io.File
/**
* 1. Check if the save path is valid
@ -30,18 +39,117 @@ import timber.log.Timber
**/
internal class HttpDGCheckInterceptor : ITaskInterceptor {
private lateinit var task: ITask
private lateinit var optionAdapter: HttpDGOptionAdapter
private lateinit var taskOption: HttpTaskOption
private val dgDao by lazy {
DuaContext.getServiceManager().getDbService().getDuaDb().getDGEntityDao()
}
override suspend fun interceptor(chain: TaskChain): TaskResp {
// if (optionAdapter.subUrl.isEmpty()){
// Timber.e("sub-task list is empty")
// return -1
// }
//
// optionAdapter.subUrl.forEach {
// if (!CheckUtil.checkUrl(it)){
// Timber.e("invalid url: $it")
// return -1
// }
// }
task = chain.getTask()
taskOption = task.getTaskOption(HttpTaskOption::class.java)
optionAdapter = taskOption.getOptionAdapter(HttpDGOptionAdapter::class.java)
if (checkParams(taskOption.savePathUri)) {
return TaskResp(TaskResp.CODE_INTERRUPT)
}
if (checkRecord()) {
return TaskResp(TaskResp.CODE_INTERRUPT)
}
return chain.proceed(task)
}
/**
* @return false interrupt task
*/
private suspend fun checkRecord(): Boolean {
val savePath = taskOption.savePathUri
val dgE = dgDao.queryDGEntityByPath(savePath.toString())
if (dgE == null) {
createNewEntity()
return true
}
val dir = File(FileUri.getPathByUri(savePath)!!)
if (dir.exists()) {
val subUrl = mutableListOf<String>()
dgE.subList.forEach { subUrl.add(it.sourceUrl) }
val diffUrl = subUrl.subtract(dgE.subList.toSet())
if (diffUrl.isNotEmpty()) {
Timber.e("invalid savePath, the path existed: $savePath, \ndiffUrl: $diffUrl")
return false
}
}
return true
}
/**
* save new record
*/
private suspend fun createNewEntity(): Boolean {
Timber.d("create new task")
// create sub task record
val dgEntity = DGEntity(
savePath = taskOption.savePathUri!!,
urls = optionAdapter.subUrlList.toList(),
subNameList = optionAdapter.subNameList
)
val subTask = mutableListOf<DEntity>()
val dir = File(FileUri.getPathByUri(taskOption.savePathUri)!!)
optionAdapter.subUrlList.forEachIndexed { index, it ->
val subName = if (optionAdapter.subNameList.isNotEmpty()) {
optionAdapter.subNameList[index]
} else {
FileUtils.getFileNameFromUrl(it) ?: "subTask_${index}"
}
val subFile = File(
dir.path,
subName
)
subTask.add(
DEntity(
sourceUrl = it,
savePath = Uri.parse(subFile.toString()),
fileName = subName
)
)
}
dgEntity.subList.addAll(subTask)
dgDao.insert(dgEntity)
return true
}
/**
* check option
* @return false interrupt task
*/
private fun checkParams(savePath: Uri?): Boolean {
if (savePath == null) {
Timber.d("save path is null")
return false
}
if (optionAdapter.subUrlList.isEmpty()) {
Timber.e("sub list is null")
return false
}
optionAdapter.subUrlList.forEach {
if (!CheckUtil.checkUrl(it)) {
Timber.e("invalid url: $it")
return false
}
}
if (optionAdapter.subNameList.isNotEmpty() && optionAdapter.subNameList.size != optionAdapter.subUrlList.size) {
Timber.e("subNameList.size must be consistent subUrlList.size")
return false
}
return true
}
}

@ -16,16 +16,15 @@
package com.arialyy.dua.group
import android.net.Uri
import com.arialyy.aria.core.command.StartCmd
import com.arialyy.aria.core.task.DownloadGroupTask
import com.arialyy.aria.core.task.ITaskInterceptor
import com.arialyy.aria.core.task.TaskCachePool
import com.arialyy.aria.http.HttpBaseStartController
import com.arialyy.aria.http.HttpOption
import com.arialyy.aria.http.HttpUtil
import com.arialyy.aria.util.FileUri
import com.arialyy.aria.util.FileUtils
import timber.log.Timber
import java.io.File
/**
* @Author laoyuyu
@ -69,10 +68,14 @@ class HttpDGStartController(target: Any, val savePath: Uri) : HttpBaseStartContr
return this
}
private fun createTask(): DownloadGroupTask {
private fun getTask(createNewTask: Boolean = true): DownloadGroupTask {
if (HttpUtil.checkHttpDParams(httpTaskOption)) {
throw IllegalArgumentException("invalid params")
}
val temp = TaskCachePool.getTaskByKey(savePath.toString())
if (temp != null) {
return temp as DownloadGroupTask
}
val task = DownloadGroupTask(httpTaskOption)
task.adapter = HttpDGroupAdapter()
TaskCachePool.putTask(task)
@ -88,15 +91,9 @@ class HttpDGStartController(target: Any, val savePath: Uri) : HttpBaseStartContr
Timber.e("invalid savePath: $savePath")
return -1
}
val dir = File(FileUri.getPathByUri(savePath)!!)
if (dir.exists()) {
Timber.e("invalid savePath, the path existed: $savePath")
return -1
}
if (optionAdapter.subNameList.isNotEmpty() && optionAdapter.subNameList.size != optionAdapter.subUrlList.size) {
Timber.e("subNameList.size must be consistent subUrlList.size")
return -1
}
return createTask().taskId
val task = getTask()
val resp = StartCmd(task).executeCmd()
return if (resp.isInterrupt()) -1 else task.taskId
}
}

@ -1,93 +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.dua.group
import android.net.Uri
import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.task.ITask
import com.arialyy.aria.core.task.ITaskInterceptor
import com.arialyy.aria.core.task.TaskChain
import com.arialyy.aria.core.task.TaskResp
import com.arialyy.aria.http.HttpTaskOption
import com.arialyy.aria.orm.entity.DEntity
import com.arialyy.aria.orm.entity.DGEntity
import com.arialyy.aria.util.FileUri
import timber.log.Timber
import java.io.File
/**
* @Author laoyuyu
* @Description
* @Date 7:27 PM 2023/3/8
**/
internal class HttpDGSubTaskInterceptor : ITaskInterceptor {
private val dgDao by lazy {
DuaContext.getServiceManager().getDbService().getDuaDb().getDGEntityDao()
}
private lateinit var task: ITask
private lateinit var option: HttpTaskOption
private lateinit var dgOption: HttpDGOptionAdapter
override suspend fun interceptor(chain: TaskChain): TaskResp {
task = chain.getTask()
option = task.getTaskOption(HttpTaskOption::class.java)
dgOption = option.getOptionAdapter(HttpDGOptionAdapter::class.java)
if (!checkRecord()) {
return TaskResp(TaskResp.CODE_INTERRUPT)
}
}
/**
* check dg task record, if dfEntiry exist, return false
* otherwise, save new record
*/
private suspend fun checkRecord(): Boolean {
val entity = dgDao.getDGEntityByPath(option.savePathUri.toString())
if (entity != null) {
Timber.e("task already exist, filePath: ${option.savePathUri}")
return false
}
// create sub task record
val dgEntity = DGEntity(
savePath = option.savePathUri!!,
urls = dgOption.subUrlList.toList(),
subNameList = dgOption.subNameList
)
val subTask = mutableListOf<DEntity>()
val dir = File(FileUri.getPathByUri(option.savePathUri)!!)
dgOption.subUrlList.forEachIndexed { index, it ->
val subFile = File(
dir.path,
if (dgOption.subNameList.isNotEmpty()) dgOption.subNameList[index] else "dgTask${index}"
)
subTask.add(
DEntity(
sourceUrl = it,
savePath = Uri.parse(subFile.toString()),
)
)
}
dgEntity.subList.addAll(subTask)
dgDao.insert(dgEntity)
return true
}
}

@ -76,9 +76,10 @@ internal class HttpDGroupAdapter : AbsTaskAdapter() {
DuaContext.duaScope.launch(Dispatchers.IO) {
Looper.prepare()
taskManager.setLooper()
addCoreInterceptor(HttpDCheckInterceptor())
addCoreInterceptor(HttpDGCheckInterceptor())
addCoreInterceptor(TimerInterceptor())
addCoreInterceptor(HttpBlockThreadInterceptor())
addCoreInterceptor()
val resp = interceptor()
if (resp == null || resp.code != TaskResp.CODE_SUCCESS) {
getTask().getTaskOption(HttpTaskOption::class.java).eventListener.onFail(

@ -49,6 +49,4 @@ public interface ITaskAdapter {
* 开始
*/
void start();
void resume();
}

@ -33,6 +33,14 @@ public class DownloadGroupTask extends AbsTask {
return DOWNLOAD_GROUP;
}
/**
* @return Always return null
*/
@Deprecated
@Override public String getUrl() {
return "";
}
@Override public String getFilePath() {
return Objects.requireNonNull(getTaskOption(TaskOption.class).getSavePathUri()).toString();
}

@ -18,7 +18,6 @@ package com.arialyy.aria.core.task
import android.net.Uri
import com.arialyy.aria.core.inf.BaseEntity
import com.arialyy.aria.core.inf.IEntity
import com.arialyy.aria.core.inf.ITaskAdapter
import timber.log.Timber
import java.util.concurrent.ConcurrentHashMap
@ -32,29 +31,38 @@ object TaskCachePool {
* key: taskId
*/
private val entityMap = ConcurrentHashMap<Int, BaseEntity>()
private val taskAdapterMap = ConcurrentHashMap<Uri, ITaskAdapter>()
/**
* task cache map; key: url
* task cache map; key: if task is [DownloadGroupTask], it's filePath else it's service url
*/
private val taskMap = ConcurrentHashMap<String, ITask>()
fun removeTask(url: String) {
taskMap.remove(url)
/**
* @param key if task is [DownloadGroupTask], it's filePath else it's service url
*/
fun removeTask(key: String) {
taskMap.remove(key)
}
/**
* if task is completed, stopped, canceled, return null
* @param key if task is [DownloadGroupTask], it's filePath else it's service url
*/
fun getTaskByUrl(url: String) = taskMap[url]
fun getTaskByKey(key: String) = taskMap[key]
fun getTaskById(taskId: Int): ITask? {
return taskMap.values.find { it.taskId == taskId }
}
fun putTask(task: ITask) {
taskMap[task.url] = task
taskAdapterMap[Uri.parse(task.filePath)] = task.adapter
when (task) {
is DownloadTask -> {
taskMap[task.url] = task
}
is DownloadGroupTask -> {
taskMap[task.filePath] = task
}
}
}
/**
@ -69,21 +77,6 @@ object TaskCachePool {
return null
}
// /**
// * @param filePath task unique identifier, like: savePath, sourceUrl
// */
// fun putTaskUtil(filePath: Uri, taskUtil: ITaskAdapter) {
// taskAdapterMap[filePath] = taskUtil
// taskUtil.stop()
// }
/**
* @param filePath unique identifier, like: savePath, sourceUrl
*/
fun getTaskAdapter(filePath: Uri): ITaskAdapter? {
return taskAdapterMap[filePath]
}
fun putEntity(taskId: Int, entity: BaseEntity) {
if (taskId <= 0) {
Timber.e("invalid taskId: $taskId")

@ -10,9 +10,6 @@ class TaskResp(val code: Int = CODE_DEF) {
const val CODE_SUCCESS = 1
const val CODE_INTERRUPT = 999
const val CODE_DEF = 0
const val CODE_SAVE_URI_NULL = 3
const val CODE_GET_FILE_INFO_FAIL = 2
const val CODE_BLOCK_QUEUE_NULL = 4
}
var fileSize: Long = 0

@ -33,16 +33,16 @@ interface DEntityDao {
@Transaction
@Query("SELECT * FROM DEntity")
suspend fun getDEntityList(): List<DEntity>
suspend fun queryDEntityList(): List<DEntity>
@Query("SELECT * FROM DEntity WHERE :savePath=savePath")
suspend fun getDEntityBySavePath(savePath: String): DEntity?
suspend fun queryDEntityBySavePath(savePath: String): DEntity?
@Query("SELECT * FROM DEntity WHERE :dId=dId")
suspend fun getDEntityById(did: String): DEntity?
suspend fun queryDEntityById(did: String): DEntity?
@Query("SELECT * FROM DEntity WHERE :sourceUrl=sourceUrl")
suspend fun getDEntityBySource(sourceUrl: String): DEntity?
suspend fun queryDEntityBySource(sourceUrl: String): DEntity?
@Insert
suspend fun insert(dEntity: DEntity)

@ -35,19 +35,19 @@ interface DGEntityDao {
@Transaction
@Query("SELECT * FROM DGEntity")
suspend fun getDGEntityList(): List<DGSubRelation>
suspend fun queryDGEntityList(): List<DGSubRelation>
@Transaction
@Query("SELECT * FROM DGEntity WHERE :path=savePath")
suspend fun getDGEntityByPath(path: String): DGSubRelation?
suspend fun queryDGEntityByPath(path: String): DGSubRelation?
@Transaction
@Query("SELECT * FROM DGEntity WHERE :gid=gid")
suspend fun getDGEntityByGid(gid: Int): DGSubRelation
suspend fun queryDGEntityByGid(gid: Int): DGSubRelation
@Transaction
@Query("SELECT * FROM DGEntity WHERE :gid=gid")
suspend fun getDGList(): List<DGSubRelation>
suspend fun queryDGList(): List<DGSubRelation>
@Insert
suspend fun insertSubList(subList: List<DEntity>)

@ -32,7 +32,7 @@ import com.arialyy.aria.orm.entity.MKeyInfo
interface MEntityDao {
@Query("SELECT * FROM MEntity WHERE :savePath=savePath")
suspend fun getMEntityByPath(savePath: String): MEntity
suspend fun queryMEntityByPath(savePath: String): MEntity
@Update
suspend fun update(entity: MEntity)

@ -35,7 +35,7 @@ interface RecordDao {
@Transaction
@Query("SELECT * FROM TaskRecord WHERE :key=taskKey")
suspend fun getTaskRecordByKey(key: String): RecordRelation?
suspend fun queryTaskRecordByKey(key: String): RecordRelation?
@Insert
@Deprecated(

@ -33,13 +33,13 @@ interface UEntityDao {
@Transaction
@Query("SELECT * FROM DEntity")
suspend fun getUEntityList(): List<UEntity>
suspend fun queryUEntityList(): List<UEntity>
@Query("SELECT * FROM DEntity WHERE :uId=uId")
suspend fun getUEntityById(uId: String): UEntity
suspend fun queryUEntityById(uId: String): UEntity
@Query("SELECT * FROM UEntity WHERE :filePath=filePath")
suspend fun getUEntityBySource(filePath: String): UEntity
suspend fun queryUEntityBySource(filePath: String): UEntity
@Insert
suspend fun insert(uEntity: UEntity)

@ -22,9 +22,11 @@ import androidx.room.PrimaryKey
import androidx.room.TypeConverters
import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.inf.BaseEntity
import com.arialyy.aria.util.FileUri
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.parcelize.Parcelize
import java.io.File
/**
* Download Entity
@ -44,11 +46,22 @@ data class DEntity(
/**
* file save path, it's uri
* eg: /mnt/Sdcard/Download/
*/
val savePath: Uri,
private val savePath: Uri,
var fileName: String = "",
val isSub: Boolean = false
) : BaseEntity() {
private var dirFile: File? = null
fun getFilePath(): String {
if (dirFile == null) {
dirFile = File(FileUri.getPathByUri(savePath)!!)
}
return File(dirFile, fileName).path
}
override fun update() {
updateTime = System.currentTimeMillis()

@ -0,0 +1,37 @@
/*
* 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.util
import java.security.MessageDigest
/**
* @Author laoyuyu
* @Description
* @Date 21:38 2023/3/11
**/
object DuaUtil {
fun getMD5Hash(str: String): String {
val md = MessageDigest.getInstance("MD5")
val messageDigest = md.digest(str.toByteArray())
val no = messageDigest.toBigInteger() // 使用 Kotlin 扩展函数将字节数组转换为 BigInteger
var hashText = no.toString(16)
while (hashText.length < 32) {
hashText = "0$hashText"
}
return hashText
}
}

@ -20,9 +20,14 @@ import android.content.pm.PackageManager
import android.net.Uri
import com.arialyy.aria.core.DuaContext
import timber.log.Timber
import java.math.BigInteger
internal const val AUTHORITY = ".andoFileProvider"
fun ByteArray.toBigInteger(): BigInteger {
return BigInteger(1, this)
}
/**
* @return 传入的Uri是否已具备访问权限 (Whether the incoming Uri has access permission)
*/

@ -34,6 +34,28 @@ object FileUtils {
RegexOption.IGNORE_CASE
)
/**
* Check if uri is a folder
* @return true it's folder
*/
fun uriIsDir(uri: Uri): Boolean {
val path = FileUri.getPathByUri(uri)
if (path.isNullOrBlank()) {
throw IllegalArgumentException("invalid uri: ${uri}")
}
return File(path).isDirectory
}
/**
* get file name from url
*/
fun getFileNameFromUrl(url: String?): String? {
if (url == null) return null
val fn = getFileNameFromPath(url) ?: return null
if (!fn.contains(".")) return null
return fn
}
/**
* 创建文件 当文件不存在的时候就创建一个文件 如果文件存在先删除原文件然后重新创建一个新文件
*

Loading…
Cancel
Save