MCPcopy
hub / github.com/hmjz100/LinkSwift / download

Function download

(改)网盘直链下载助手.user.js:1240–1446  ·  view source on GitHub ↗

* 下载文件 * @author hmjz100 * @description 发送 GET 请求,一般用于文件下载,支持进度监控、自动重试、断点续传、非断回退 * @param {String} url - 请求地址 * @param {Object} headers - 请求头配置 * @param {Number} [size=0] - 响应类型 * @param {Object} [extra] - 附加参数(必须 `name`、`index`、`size` 属性;可选 `thread`、`retry` 属性) * @return

(url, headers, extra)

Source from the content-addressed store, hash-verified

1238 * @returns {Promise} 包含响应数据的 `Promise` 对象
1239 */
1240 async download(url, headers, extra) {
1241 headers = this.standHeaders(headers);
1242 // 初始化全局共享状态
1243 this.download.active = this.download.active || 0; // 全局活跃线程数
1244 this.download.taskCount = this.download.taskCount || 0; // 当前正在运行的 download 任务数
1245 var global_maxThreads = 8; // 整个允许的最大并发数
1246
1247 if (extra) base.console.log(`【LinkSwift】Download\n收到数据:`, extra);
1248 if (!extra || !extra.index || !extra.name || !extra.size) throw new Error("extra 缺少内容。");
1249
1250 let status = {
1251 aborted: false,
1252 requests: new Set(),
1253 results: [],
1254 active: 0,
1255 maxSpeed: 0
1256 };
1257
1258 let promise = new Promise(async (resolve, reject) => {
1259 this.download.taskCount++; // 任务进入
1260
1261 try {
1262 var finalHead = await base.getFinal(url, headers, false, false).catch(reject);
1263 if (!finalHead) return;
1264 url = finalHead.finalUrl;
1265
1266 var responseHeaders = finalHead.responseHeaders;
1267 let size = parseInt(extra.size || responseHeaders?.["Content-Length"] || 0, 10);
1268 if (responseHeaders?.["Content-Range"]) {
1269 size = parseInt((responseHeaders["Content-Range"]?.match(/\/(\d+)$/)?.[1] || size), 10);
1270 }
1271
1272 if (!status.aborted && typeof extra?.onProgress === "function") extra.onProgress(0, 0, size);
1273 if (!(finalHead.status >= 200 && finalHead.status < 400)) return reject(finalHead);
1274 if (finalHead.status == 204 && finalHead.statusText === "IDM") return reject(finalHead);
1275
1276 var supportRange = finalHead.status == 206 && (responseHeaders?.["Accept-Ranges"]?.includes("bytes") || responseHeaders?.["Content-Range"]?.includes("bytes"));
1277
1278 if (!!supportRange || size > 0) {
1279 base.console.log(`【LinkSwift】Download(Start)\n文件名称:${extra.name}\n断点续传:支持`);
1280
1281 var maxRetry = extra.retry || 10;
1282 let index = 0;
1283 let offset = 0;
1284 let totalLoaded = 0;
1285
1286 var worker = async () => {
1287 var minChunk = extra.minChunk || 50 * 1024; // 最小 50KB
1288 var maxChunk = extra.maxChunk || 1 * 1024 * 1024; // 最大 1MB
1289 let chunk = Math.floor(minChunk + (maxChunk - minChunk) * 0.37);
1290
1291 while (offset < size && !status.aborted) {
1292 // 如果全局线程满了,且当前任务已经抢到了 1 条以上的线程,则 “让路” 给后来的任务
1293 let fairShare = Math.max(1, Math.floor(global_maxThreads / this.download.taskCount));
1294 while (!status.aborted && this.download.active >= global_maxThreads && status.active >= fairShare) {
1295 await new Promise(r => setTimeout(r, 200)); // 等待,直到其他任务释放或有空位
1296 }
1297

Callers

nothing calls this directly

Calls 1

getBlobDataFunction · 0.85

Tested by

no test coverage detected