kt携程版本

This commit is contained in:
lushunming 2025-07-11 11:48:06 +08:00
parent 191d961f84
commit ad148795a8
4 changed files with 152 additions and 2 deletions

View File

@ -0,0 +1,150 @@
package com.github.catvod.utils
import com.github.catvod.crawler.SpiderDebug
import com.github.catvod.net.OkHttp
import com.github.catvod.utils.ProxyVideo.generatePart
import com.github.catvod.utils.ProxyVideo.getInfo
import com.github.catvod.utils.ProxyVideo.getMimeType
import com.github.catvod.utils.ProxyVideo.parseRange
import com.github.catvod.utils.ProxyVideo.proxy
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.joinAll
import kotlinx.coroutines.launch
import okhttp3.Response
import org.apache.commons.lang3.StringUtils
import java.io.InputStream
import java.io.SequenceInputStream
import java.util.Vector
object DownloadMT {
val THREAD_NUM: Int = Runtime.getRuntime().availableProcessors() * 2
private val infos = mutableMapOf<String, Array<Any>>();
fun proxyMultiThread(url: String, headers: Map<String, String>): Array<out Any?>? {
/* val service = Executors.newFixedThreadPool(THREAD_NUM)
SpiderDebug.log("--proxyMultiThread: THREAD_NUM " + THREAD_NUM)*/
val `in`: SequenceInputStream?
try {
//缓存避免每次都请求total等信息
val info = infos[url]
if (info == null) {
infos.clear()
infos[url] = getInfo(url, headers)
}
val code = info?.get(0) as Int
if (code != 206) {
return proxy(url, headers)
}
val resHeader = info[3] as MutableMap<String, String>
val contentRange =
if (StringUtils.isAllBlank(resHeader["Content-Range"])) resHeader["content-range"] else resHeader["Content-Range"]
SpiderDebug.log("--contentRange:$contentRange")
//文件总大小
val total = StringUtils.split(contentRange, "/")[1]
SpiderDebug.log("--文件总大小:$total")
//如果文件太小,也不走代理
if (total.toLong() < 1024 * 1024 * 100) {
return proxy(url, headers)
}
var range =
if (StringUtils.isAllBlank(headers["range"])) headers["Range"] else headers["range"]
if (StringUtils.isAllBlank(range)) range = "bytes=0-";
SpiderDebug.log("---proxyMultiThread,Range:$range")
val rangeObj = parseRange(
range!!
)
//没有range,无需分割
val partList = generatePart(rangeObj, total)
// 存储执行结果的List
val jobs = mutableListOf<Job>()
val channels = List(THREAD_NUM) { Channel<Response>() }
for ((index, part) in partList.withIndex()) {
val newRange = "bytes=" + part[0] + "-" + part[1]
SpiderDebug.log("下载开始;newRange:$newRange")
val headerNew: MutableMap<String, String> = HashMap(headers)
headerNew["range"] = newRange
headerNew["Range"] = newRange
jobs += CoroutineScope(Dispatchers.IO).launch {
downloadRange(url, headerNew)?.let { channels[index].send(it) };
}
}
val inputStreams: MutableList<InputStream> = ArrayList()
CoroutineScope(Dispatchers.Default).launch {
repeat(jobs.size) { index ->
launch {
val response = channels[index].receive()
val body = response.body();/* int bytesRead;
while ((bytesRead = body.byteStream().read(bytes)) != -1) {
out.write(bytes, 0, bytesRead);
}*/
inputStreams.add(body!!.byteStream())
SpiderDebug.log("---第" + index + "块下载完成" + ";Content-Range:" + response.headers()["Content-Range"])
SpiderDebug.log("---第" + index + "块下载完成" + ";content-range:" + response.headers()["content-range"])
}
}
// 等待所有下载完成
jobs.joinAll()
}
`in` = SequenceInputStream(Vector(inputStreams).elements())
// SpiderDebug.log(" ++proxy res data:" + Json.toJson(response.body()));
var contentType: String? = if (StringUtils.isAllBlank(
resHeader["Content-Type"]
)
) resHeader["content-type"] else resHeader["Content-Type"]
val contentDisposition: String = resHeader["Content-Disposition"]!!.toString()
if (StringUtils.isAllBlank(contentType)&& StringUtils.isNoneBlank(contentDisposition)) {
contentType = getMimeType(contentDisposition)
}
/* respHeaders.put("Access-Control-Allow-Credentials", "true");
respHeaders.put("Access-Control-Allow-Origin", "*");*/
resHeader["Content-Length"] =
(partList[THREAD_NUM - 1][1] - partList[0][0] + 1).toString()
// respHeaders.put("content-length", String.valueOf(bytes.length));
resHeader["Content-Range"] = String.format(
"bytes %s-%s/%s", partList[0][0], partList[THREAD_NUM - 1][1], total
)
// respHeaders.put("content-range", String.format("bytes %s-%s/%s", partList.get(0)[0], partList.get(THREAD_NUM - 1)[1], total));
SpiderDebug.log("++proxy res contentType:$contentType")
// SpiderDebug.log("++proxy res body:" + response.body());
SpiderDebug.log("++proxy res respHeaders:" + Json.toJson(resHeader))
return arrayOf(206, contentType, `in`, resHeader)
} catch (e: Exception) {
SpiderDebug.log("proxyMultiThread error:" + e.message)
e.printStackTrace()
return null
}
}
private fun downloadRange(
url: String, headerNew: MutableMap<String, String>
): Response? = OkHttp.newCall(url, headerNew)
}

Binary file not shown.

View File

@ -1 +1 @@
860afdcd1a39fd5c0bcfae2b0652ec7c
2d18b21a13a3e7b982f1d1642d975c9b

View File

@ -1,5 +1,5 @@
{
"spider": "https://gh-proxy.com/https://raw.githubusercontent.com/lushunming/AndroidCatVodSpider/multiThreadkt/jar/custom_spider.jar;md5;860afdcd1a39fd5c0bcfae2b0652ec7c",
"spider": "https://gh-proxy.com/https://raw.githubusercontent.com/lushunming/AndroidCatVodSpider/multiThreadkt/jar/custom_spider.jar;md5;2d18b21a13a3e7b982f1d1642d975c9b",
"lives": [
{
"name": "电视直播",