多线程内存分割
This commit is contained in:
parent
e41998b0c5
commit
272d9db20c
|
|
@ -7,6 +7,7 @@ import com.github.catvod.net.OkHttp;
|
||||||
import com.github.catvod.spider.Proxy;
|
import com.github.catvod.spider.Proxy;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
|
@ -14,14 +15,18 @@ import java.io.ByteArrayInputStream;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
public class ProxyVideo {
|
public class ProxyVideo {
|
||||||
|
|
||||||
private static final String GO_SERVER = "http://127.0.0.1:7777/";
|
private static final String GO_SERVER = "http://127.0.0.1:7777/";
|
||||||
//线程数4
|
//线程数4
|
||||||
private static final int THREAD_NUM = 16;
|
private static final int THREAD_NUM = 16;
|
||||||
private static Map<String, Object[]> infoMap = new ConcurrentHashMap<>();
|
|
||||||
|
private static final ExecutorService service = Executors.newFixedThreadPool(THREAD_NUM);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static String buildCommonProxyUrl(String url, Map<String, String> headers) {
|
public static String buildCommonProxyUrl(String url, Map<String, String> headers) {
|
||||||
|
|
@ -77,19 +82,11 @@ public class ProxyVideo {
|
||||||
|
|
||||||
|
|
||||||
public static Object[] proxyMultiThread(String url, Map<String, String> headers) throws Exception {
|
public static Object[] proxyMultiThread(String url, Map<String, String> headers) throws Exception {
|
||||||
Object[] info = infoMap.get(url);
|
|
||||||
|
|
||||||
//防止频繁请求
|
|
||||||
if (info == null) {
|
|
||||||
Map<String, String> newHeaders = new HashMap<>(headers);
|
|
||||||
newHeaders.put("range", "bytes=0-0");
|
|
||||||
newHeaders.put("Range", "bytes=0-0");
|
|
||||||
info = proxy(url, newHeaders);
|
|
||||||
infoMap.clear();
|
|
||||||
infoMap.put(url, info);
|
|
||||||
}
|
|
||||||
|
|
||||||
SpiderDebug.log("--proxyMultiThread: start ");
|
SpiderDebug.log("--proxyMultiThread: start ");
|
||||||
|
Map<String, String> newHeaders = new HashMap<>(headers);
|
||||||
|
newHeaders.put("range", "bytes=0-0");
|
||||||
|
newHeaders.put("Range", "bytes=0-0");
|
||||||
|
Object[] info = proxy(url, newHeaders);
|
||||||
int code = (int) info[0];
|
int code = (int) info[0];
|
||||||
if (code != 206) {
|
if (code != 206) {
|
||||||
return proxy(url, headers);
|
return proxy(url, headers);
|
||||||
|
|
@ -109,20 +106,62 @@ public class ProxyVideo {
|
||||||
SpiderDebug.log("没有range,无需分割");
|
SpiderDebug.log("没有range,无需分割");
|
||||||
return proxy(url, headers);
|
return proxy(url, headers);
|
||||||
} else {
|
} else {
|
||||||
|
List<long[]> partList = generatePart(rangeObj, total);
|
||||||
|
|
||||||
|
// 存储执行结果的List
|
||||||
|
List<Future<Response>> results = new ArrayList<>();
|
||||||
|
for (long[] part : partList) {
|
||||||
|
|
||||||
DownloadService.get().submitDownload(url, headers, Long.parseLong(total));
|
String newRange = "bytes=" + part[0] + "-" + part[1];
|
||||||
Object[] res = DownloadService.get().getDownloadBytes(Long.parseLong(rangeObj.get("start")));
|
SpiderDebug.log("下载开始" + ";newRange:" + newRange);
|
||||||
|
|
||||||
|
Map<String, String> headerNew = new HashMap<>(headers);
|
||||||
|
|
||||||
|
headerNew.put("range", newRange);
|
||||||
|
headerNew.put("Range", newRange);
|
||||||
|
Future<Response> result = service.submit(() -> {
|
||||||
|
try {
|
||||||
|
|
||||||
|
return OkHttp.newCall(url, headerNew);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
results.add(result);
|
||||||
|
}
|
||||||
|
byte[] bytes = null;
|
||||||
|
|
||||||
|
Response response = null;
|
||||||
|
for (int i = 0; i < THREAD_NUM; i++) {
|
||||||
|
// 获取包含返回结果的future对象
|
||||||
|
Future<Response> future = results.get(i);
|
||||||
|
// 从future中取出执行结果(若尚未返回结果,则get方法被阻塞,直到结果被返回为止)
|
||||||
|
response = future.get();
|
||||||
|
bytes = ArrayUtils.addAll(bytes, response.body().bytes());
|
||||||
|
SpiderDebug.log("---第" + i + "块下载完成" + ";Content-Range:" + response.headers().get("Content-Range"));
|
||||||
|
SpiderDebug.log("---第" + i + "块下载完成" + ";content-range:" + response.headers().get("content-range"));
|
||||||
|
|
||||||
|
}
|
||||||
|
service.shutdown();
|
||||||
|
String contentType = response.headers().get("Content-Type");
|
||||||
|
String contentDisposition = response.headers().get("Content-Disposition");
|
||||||
|
if (contentDisposition != null) contentType = getMimeType(contentDisposition);
|
||||||
Map<String, String> respHeaders = new HashMap<>();
|
Map<String, String> respHeaders = new HashMap<>();
|
||||||
|
/* respHeaders.put("Access-Control-Allow-Credentials", "true");
|
||||||
|
respHeaders.put("Access-Control-Allow-Origin", "*");*/
|
||||||
|
|
||||||
|
for (String key : response.headers().names()) {
|
||||||
|
respHeaders.put(key, response.headers().get(key));
|
||||||
|
}
|
||||||
|
|
||||||
respHeaders.put("Content-Length", ((long) res[1] - (long) res[0] + 1) + "");
|
respHeaders.put("Content-Length", String.valueOf(bytes.length));
|
||||||
respHeaders.put("content-length", ((long) res[1] - (long) res[0] + 1) + "");
|
respHeaders.put("content-length", String.valueOf(bytes.length));
|
||||||
respHeaders.put("Content-Range", String.format("bytes %s-%s/%s", res[1], res[2], total));
|
respHeaders.put("Content-Range", String.format("bytes %s-%s/%s", partList.get(0)[0], partList.get(THREAD_NUM - 1)[1], total));
|
||||||
respHeaders.put("content-range", String.format("bytes %s-%s/%s", res[1], res[2], 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);
|
||||||
return new Object[]{206, "video/mp4", new ByteArrayInputStream((byte[]) res[0]), respHeaders};
|
// SpiderDebug.log("++proxy res body:" + response.body());
|
||||||
|
SpiderDebug.log("++proxy res respHeaders:" + Json.toJson(respHeaders));
|
||||||
|
return new Object[]{response.code(), contentType, new ByteArrayInputStream(bytes), respHeaders};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -130,19 +169,15 @@ public class ProxyVideo {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<long[]> generatePart(Map<String, String> rangeObj, String total) {
|
private static List<long[]> generatePart(Map<String, String> rangeObj, String total) {
|
||||||
SpiderDebug.log("generatePart.total:" + total);
|
|
||||||
long start = Long.parseLong(rangeObj.get("start"));
|
long start = Long.parseLong(rangeObj.get("start"));
|
||||||
long end = StringUtils.isAllBlank(rangeObj.get("end")) ? start + 1024 * 1024 * 8 : Long.parseLong(rangeObj.get("end"));
|
long end = StringUtils.isAllBlank(rangeObj.get("end")) ? start + 1024 * 1024 *8 : Long.parseLong(rangeObj.get("end"));
|
||||||
|
|
||||||
|
|
||||||
long totalSize = Long.parseLong(total);
|
long totalSize = Long.parseLong(total);
|
||||||
end = Math.min(end, totalSize - 1);
|
end = Math.min(end, totalSize - 1);
|
||||||
long length = end - start + 1;
|
long length = end - start + 1;
|
||||||
SpiderDebug.log("generatePart.start:" + start);
|
|
||||||
SpiderDebug.log("generatePart.end:" + end);
|
|
||||||
SpiderDebug.log("generatePart.length:" + length);
|
|
||||||
long size = length / THREAD_NUM;
|
long size = length / THREAD_NUM;
|
||||||
SpiderDebug.log("generatePart.size:" + size);
|
|
||||||
List<long[]> partList = new ArrayList<>();
|
List<long[]> partList = new ArrayList<>();
|
||||||
for (int i = 0; i < THREAD_NUM; i++) {
|
for (int i = 0; i < THREAD_NUM; i++) {
|
||||||
long partEnd = Math.min(start + size, end);
|
long partEnd = Math.min(start + size, end);
|
||||||
|
|
@ -201,4 +236,4 @@ public class ProxyVideo {
|
||||||
* 视频range
|
* 视频range
|
||||||
*/
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
Binary file not shown.
|
|
@ -1 +1 @@
|
||||||
0b44917627bcbe34d8a552b321a55571
|
5abe7e76705934af62d214ed64044353
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"spider": "https://ghproxy.net/https://raw.githubusercontent.com/lushunming/AndroidCatVodSpider/multiThread/jar/custom_spider.jar;md5;0b44917627bcbe34d8a552b321a55571",
|
"spider": "https://ghproxy.net/https://raw.githubusercontent.com/lushunming/AndroidCatVodSpider/multiThread/jar/custom_spider.jar;md5;5abe7e76705934af62d214ed64044353",
|
||||||
"lives": [
|
"lives": [
|
||||||
{
|
{
|
||||||
"name": "电视直播",
|
"name": "电视直播",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue