http file info

v4
lyy 2 years ago
parent 3fd103d616
commit b378d9e3f2
  1. 42
      Http/src/main/java/com/arialyy/aria/http/download/HttpDHeaderInterceptor.kt
  2. 28
      Http/src/main/java/com/arialyy/aria/http/download/HttpDStartController.kt
  3. 8
      Http/src/main/java/com/arialyy/aria/http/download/HttpDTaskOption.kt
  4. 17
      Http/src/main/java/com/arialyy/aria/http/download/HttpDTaskUtil.kt
  5. 10
      PublicComponent/src/main/java/com/arialyy/aria/core/task/AbsTaskUtil.kt

@ -40,7 +40,7 @@ import java.util.UUID
* @Description
* @Date 2:27 PM 2023/1/28
**/
internal class HttpHeaderInterceptor : ITaskInterceptor {
internal class HttpDHeaderInterceptor : ITaskInterceptor {
private lateinit var task: ITask
private lateinit var taskOption: HttpDTaskOption
@ -53,22 +53,27 @@ internal class HttpHeaderInterceptor : ITaskInterceptor {
override fun interceptor(chain: TaskChain): TaskResp {
if (Looper.myLooper() == Looper.getMainLooper()) {
throw IllegalThreadStateException("Io operations cannot be in the main thread")
throw IllegalThreadStateException("io operations cannot be in the main thread")
}
Timber.i("step 1. get file info")
task = chain.getTask()
taskOption = task.getTaskOption(HttpDTaskOption::class.java)
return try {
try {
val fileSize = getFileSize()
chain.proceed(task)
if (fileSize >= 0) {
task.taskState.fileSize = fileSize
return chain.proceed(task)
}
} catch (e: IOException) {
Timber.e(
"download fail, url: ${
chain.getTask().getTaskOption(HttpDTaskOption::class.java).sourUrl
}"
)
TaskResp(TaskResp.CODE_GET_FILE_INFO_FAIL)
return TaskResp(TaskResp.CODE_GET_FILE_INFO_FAIL)
}
Timber.e("can't get fileSize")
return TaskResp(TaskResp.CODE_INTERRUPT)
}
@Throws(IOException::class)
@ -78,8 +83,8 @@ internal class HttpHeaderInterceptor : ITaskInterceptor {
val conn: HttpURLConnection = IRequest.getRequest(taskOption.httpOption!!)
.getDConnection(taskOption.sourUrl!!, taskOption.httpOption!!)
// https://httpwg.org/specs/rfc9110.html#byte.ranges
// conn.setRequestProperty("Range", "bytes=" + 0 + "-")
conn.setRequestProperty("Range", "bytes=0-1") // 尝试获取1个字节
conn.setRequestProperty("Range", "bytes=0-")
// conn.setRequestProperty("Range", "bytes=0-1") // 尝试获取1个字节
conn.connect()
return handleConnect(conn)
}
@ -109,9 +114,17 @@ internal class HttpHeaderInterceptor : ITaskInterceptor {
reader.close()
return handleUrlReTurn(conn, HttpUtil.getWindowReplaceUrl(sb.toString()))
}
val chunkSize = checkChunkFileSize(conn)
if (chunkSize > -1) {
Timber.d("the url is chunk task, ${conn.url}")
return chunkSize
}
// code is 200, but file size cannot be obtained.
return -1
}
code == 416 -> {
return getFileSizeFromHeader(conn.headerFields, taskOption)
}
code in CODE_30X -> {
Timber.d("handle 30x turn, code: $code")
return handleUrlReTurn(conn, conn.getHeaderField("Location"))
@ -126,6 +139,19 @@ internal class HttpHeaderInterceptor : ITaskInterceptor {
}
}
/**
* if headers has [rfc9112 Transfer-Encoding](https://httpwg.org/specs/rfc9112.html#chunked.trailer.section)
* the url is chunk task
*/
private fun checkChunkFileSize(conn: HttpURLConnection): Long {
val chunkHead = conn.headerFields["Transfer-Encoding"]
if (chunkHead.isNullOrEmpty()) {
return -1
}
taskOption.isChunkTask = true
return 0
}
@Throws(IOException::class) private fun handleUrlReTurn(
oldConn: HttpURLConnection,
newUrl: String?

@ -22,12 +22,14 @@ import com.arialyy.aria.core.command.StartCmd
import com.arialyy.aria.core.inf.IStartController
import com.arialyy.aria.core.processor.IHttpFileLenAdapter
import com.arialyy.aria.core.task.DownloadTask
import com.arialyy.aria.core.task.ITaskInterceptor
import com.arialyy.aria.core.task.TaskCachePool
import com.arialyy.aria.http.HttpBaseController
import com.arialyy.aria.http.HttpOption
import com.arialyy.aria.http.HttpUtil
import com.arialyy.aria.orm.entity.DEntity
import kotlinx.coroutines.launch
import timber.log.Timber
import java.net.HttpURLConnection
/**
@ -44,6 +46,19 @@ class HttpDStartController(target: Any, val url: String) : HttpBaseController(ta
httpDTaskOption.sourUrl = url
}
/**
* use multi-threaded download file, if file size <= 5m, this setting is not valid
* @param threadNum range [1 - 32]
*/
fun setThreadNum(threadNum: Long): HttpDStartController {
if (threadNum !in 1..32) {
Timber.e("set thread num fail, only 0 < threadNum < 33, threadNum: $threadNum")
return this
}
httpDTaskOption.threadNum = threadNum
return this
}
/**
* set http params, link Header
*/
@ -56,11 +71,22 @@ class HttpDStartController(target: Any, val url: String) : HttpBaseController(ta
* Maybe the server has special rules, you need set [IHttpFileLenAdapter] to get the file length from [HttpURLConnection.getHeaderFields]
*/
fun setHttpFileLenAdapter(adapter: IHttpFileLenAdapter): HttpDStartController {
httpDTaskOption.fileSizeAdapter = adapter
return this
}
/**
* if you want to do something before the task is executed, you can set up a task interceptor
* eg: determine the network status before task execution
*/
fun setTaskInterceptor(taskInterceptor: ITaskInterceptor): HttpDStartController {
httpDTaskOption.taskInterceptor.add(taskInterceptor)
return this
}
/**
* set download listener
*/
fun setListener(listener: HttpDownloadListener): HttpDStartController {
DuaContext.getLifeManager().addCustomListener(target, listener)
return this

@ -17,6 +17,7 @@ package com.arialyy.aria.http.download
import com.arialyy.aria.core.download.DTaskOption
import com.arialyy.aria.core.processor.IHttpFileLenAdapter
import com.arialyy.aria.core.task.ITaskInterceptor
import com.arialyy.aria.http.HttpOption
/**
@ -26,6 +27,13 @@ import com.arialyy.aria.http.HttpOption
**/
class HttpDTaskOption : DTaskOption() {
companion object {
const val BLOCK_SIZE = 1024 * 1024 * 5
}
var httpOption: HttpOption? = null
var fileSizeAdapter: IHttpFileLenAdapter? = null
var taskInterceptor = mutableListOf<ITaskInterceptor>()
var isChunkTask = false
var threadNum: Long = 1L
}

@ -1,6 +1,9 @@
package com.arialyy.aria.http.download
import com.arialyy.aria.core.DuaContext
import com.arialyy.aria.core.task.AbsTaskUtil
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
/**
* @Author laoyuyu
@ -9,10 +12,6 @@ import com.arialyy.aria.core.task.AbsTaskUtil
**/
internal class HttpDTaskUtil : AbsTaskUtil() {
init {
}
override fun isRunning(): Boolean {
TODO("Not yet implemented")
}
@ -26,6 +25,14 @@ internal class HttpDTaskUtil : AbsTaskUtil() {
}
override fun start() {
getTask().getTaskOption(HttpDTaskOption::class.java).taskInterceptor.let {
if (it.isNotEmpty()) {
addInterceptors(it)
}
}
addCoreInterceptor(HttpDHeaderInterceptor())
DuaContext.duaScope.launch(Dispatchers.IO) {
val resp = interceptor()
}
}
}

@ -25,8 +25,8 @@ import com.arialyy.aria.core.task.ITaskInterceptor.IChain
* @Date 1:12 PM 2023/1/28
**/
abstract class AbsTaskUtil : ITaskUtil {
protected lateinit var mTask: ITask
protected lateinit var mEventListener: IEventListener
private lateinit var mTask: ITask
private lateinit var mEventListener: IEventListener
private val mUserInterceptor = mutableListOf<ITaskInterceptor>()
private val mCoreInterceptor = mutableListOf<ITaskInterceptor>()
@ -36,14 +36,16 @@ abstract class AbsTaskUtil : ITaskUtil {
mEventListener = listener
}
protected fun getTask() = mTask
/**
* add user interceptor
*/
open fun setInterceptors(userInterceptors: List<ITaskInterceptor>) {
protected fun addInterceptors(userInterceptors: List<ITaskInterceptor>) {
mUserInterceptor.addAll(userInterceptors)
}
protected open fun addCoreInterceptor(interceptor: ITaskInterceptor) {
protected fun addCoreInterceptor(interceptor: ITaskInterceptor) {
mCoreInterceptor.add(interceptor)
}

Loading…
Cancel
Save