| 
						
						
							
								
							
						
						
					 | 
					 | 
					@ -40,7 +40,7 @@ import java.util.UUID | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * @Description | 
					 | 
					 | 
					 | 
					 * @Description | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 * @Date 2:27 PM 2023/1/28 | 
					 | 
					 | 
					 | 
					 * @Date 2:27 PM 2023/1/28 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 **/ | 
					 | 
					 | 
					 | 
					 **/ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					internal class HttpHeaderInterceptor : ITaskInterceptor { | 
					 | 
					 | 
					 | 
					internal class HttpDHeaderInterceptor : ITaskInterceptor { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  private lateinit var task: ITask | 
					 | 
					 | 
					 | 
					  private lateinit var task: ITask | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  private lateinit var taskOption: HttpDTaskOption | 
					 | 
					 | 
					 | 
					  private lateinit var taskOption: HttpDTaskOption | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -53,22 +53,27 @@ internal class HttpHeaderInterceptor : ITaskInterceptor { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  override fun interceptor(chain: TaskChain): TaskResp { | 
					 | 
					 | 
					 | 
					  override fun interceptor(chain: TaskChain): TaskResp { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if (Looper.myLooper() == Looper.getMainLooper()) { | 
					 | 
					 | 
					 | 
					    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() | 
					 | 
					 | 
					 | 
					    task = chain.getTask() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    taskOption = task.getTaskOption(HttpDTaskOption::class.java) | 
					 | 
					 | 
					 | 
					    taskOption = task.getTaskOption(HttpDTaskOption::class.java) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return try { | 
					 | 
					 | 
					 | 
					    try { | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      val fileSize = getFileSize() | 
					 | 
					 | 
					 | 
					      val fileSize = getFileSize() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					      if (fileSize >= 0) { | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      chain.proceed(task) | 
					 | 
					 | 
					 | 
					        task.taskState.fileSize = fileSize | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        return chain.proceed(task) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    } catch (e: IOException) { | 
					 | 
					 | 
					 | 
					    } catch (e: IOException) { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      Timber.e( | 
					 | 
					 | 
					 | 
					      Timber.e( | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        "download fail, url: ${ | 
					 | 
					 | 
					 | 
					        "download fail, url: ${ | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          chain.getTask().getTaskOption(HttpDTaskOption::class.java).sourUrl | 
					 | 
					 | 
					 | 
					          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) | 
					 | 
					 | 
					 | 
					  @Throws(IOException::class) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					 | 
					@ -78,8 +83,8 @@ internal class HttpHeaderInterceptor : ITaskInterceptor { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    val conn: HttpURLConnection = IRequest.getRequest(taskOption.httpOption!!) | 
					 | 
					 | 
					 | 
					    val conn: HttpURLConnection = IRequest.getRequest(taskOption.httpOption!!) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      .getDConnection(taskOption.sourUrl!!, taskOption.httpOption!!) | 
					 | 
					 | 
					 | 
					      .getDConnection(taskOption.sourUrl!!, taskOption.httpOption!!) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // https://httpwg.org/specs/rfc9110.html#byte.ranges | 
					 | 
					 | 
					 | 
					    // https://httpwg.org/specs/rfc9110.html#byte.ranges | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    // conn.setRequestProperty("Range", "bytes=" + 0 + "-") | 
					 | 
					 | 
					 | 
					    conn.setRequestProperty("Range", "bytes=0-") | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    conn.setRequestProperty("Range", "bytes=0-1") // 尝试获取1个字节 | 
					 | 
					 | 
					 | 
					    // conn.setRequestProperty("Range", "bytes=0-1") // 尝试获取1个字节 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    conn.connect() | 
					 | 
					 | 
					 | 
					    conn.connect() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    return handleConnect(conn) | 
					 | 
					 | 
					 | 
					    return handleConnect(conn) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					  } | 
					 | 
					 | 
					 | 
					  } | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					 | 
					@ -109,9 +114,17 @@ internal class HttpHeaderInterceptor : ITaskInterceptor { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          reader.close() | 
					 | 
					 | 
					 | 
					          reader.close() | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					          return handleUrlReTurn(conn, HttpUtil.getWindowReplaceUrl(sb.toString())) | 
					 | 
					 | 
					 | 
					          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. | 
					 | 
					 | 
					 | 
					        // code is 200, but file size cannot be obtained. | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        return -1 | 
					 | 
					 | 
					 | 
					        return -1 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      } | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      code == 416 -> { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        return getFileSizeFromHeader(conn.headerFields, taskOption) | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					      } | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					      code in CODE_30X -> { | 
					 | 
					 | 
					 | 
					      code in CODE_30X -> { | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        Timber.d("handle 30x turn, code: $code") | 
					 | 
					 | 
					 | 
					        Timber.d("handle 30x turn, code: $code") | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        return handleUrlReTurn(conn, conn.getHeaderField("Location")) | 
					 | 
					 | 
					 | 
					        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( | 
					 | 
					 | 
					 | 
					  @Throws(IOException::class) private fun handleUrlReTurn( | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    oldConn: HttpURLConnection, | 
					 | 
					 | 
					 | 
					    oldConn: HttpURLConnection, | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    newUrl: String? | 
					 | 
					 | 
					 | 
					    newUrl: String? |