// 定义一个名为download的异步函数,参数为blob和fileName // 用window.URL.createObjectURL()方法创建一个URL对象 // 创建一个a标签,设置download属性为fileName,href属性为link,将a标签添加到body中 // 使用a.click()方法模拟点击a标签下载文件,完成后将a标签移除 // 使用window.URL.revokeObjectURL()方法释放URL对象的内存 var download = async (blob, fileName) => { let link = window.URL.createObjectURL(blob); const a = document.createElement("a"); a.download = ${fileName}; a.href = link; document.body.appendChild(a); a.click(); document.body.removeChild(a); window.URL.revokeObjectURL(link); };

// 定义一个名为safetyParse的函数,参数为str // 使用try...catch语句尝试将str转换成JSON对象,如果转换失败则返回null var safetyParse = (str) => { try { return JSON.parse(str); } catch (error) { return null; } };

// 定义一个名为getFile的异步函数,参数为url // 使用fetch()方法获取url对应资源的响应对象res // 使用res.body.getReader()方法获取一个ReadableStream对象的reader // 使用res.headers.get()方法获取响应头中Content-Length字段的值,如果不存在则说明响应体没有长度限制,直接使用res.arrayBuffer()方法获取响应体的二进制数据 // 使用while循环不断从ReadableStream中读取数据,直到读取完毕 // 将每次读取的数据块存入chunks数组中,并累加receivedLength变量的值 // 返回一个Blob对象,该Blob对象包含所有读取到的数据块 var getFile = async (url) => { const res = await fetch(url); const reader = res.body.getReader(); const contentLength = +res.headers.get("Content-Length"); if (!contentLength) { const data = await res.arrayBuffer(); return new Uint8Array(data); } let receivedLength = 0; let chunks = []; while (true) { const { done, value } = await reader.read(); if (done) { break; } chunks.push(value); receivedLength += value.length; console.log( fileSize: ${contentLength} %c downloaded ${receivedLength}, "background: #222; color: #bada55" ); } return new Blob(chunks); };

// 定义一个名为getUrlsByM3u8的异步函数,参数为url和parser // 使用URL()方法创建一个URL对象urlObj,将url中的pathname去掉最后一段,将search设为空字符串 // 将urlObj转换成字符串形式,得到base // 使用fetch()方法获取url对应资源的响应对象res // 使用res.text()方法获取响应体的文本数据data // 将data按行切分成数组,过滤掉空行和以#开头的行 // 遍历剩下的行,如果parser存在则使用parser方法处理,否则根据行内容判断是绝对路径还是相对路径并拼接成完整的url // 返回一个数组,包含所有处理过的url var getUrlsByM3u8 = async (url, parser) => { const urlObj = new URL(url); urlObj.pathname = urlObj.pathname.split("/").slice(0, -1).join("/"); urlObj.search = ""; const base = urlObj.toString(); const res = await fetch(url); const data = await res.text(); return data.split("\n").filter((i) => !!i && !i.startsWith("#")).map((i) => { if (parser) { return parser(i); } return i.startsWith("/") ? ${base}${i} : ${base}/${i}; }); };

// 定义一个名为getFiles的函数,参数为urls和max // 将urls数组中的每个元素添加一个index属性,值为该元素在数组中的下标 // 返回一个Promise对象,该Promise对象在所有请求完成后resolve一个数组,数组中包含所有请求返回的数据 // 先创建一个长度为max的空数组connections,表示同时允许max个请求在进行 // 再创建一个空数组files,用于存放所有请求返回的数据 // 使用for循环遍历urls数组,对于每个元素,将其添加到connections数组中 // 如果connections数组长度达到了max,说明已经有max个请求在进行,需要等待其中一个请求完成后再继续发起请求 // 这里使用Promise.race()方法返回一个Promise对象,当connections数组中有元素变成undefined时,说明对应的请求已经完成,这个Promise对象就resolve并返回该请求返回的数据 // 使用Promise.all()方法等待所有请求完成,并将所有请求返回的数据存入files数组中 // 最后返回files数组 var getFiles = (urls, max = 8) => { let connections = new Array(max); let files = []; urls = urls.map((i, index) => ({ ...i, index })); return new Promise((resolve) => { (async () => { for (let i = 0; i < urls.length; i++) { let url = urls[i]; connections.push(url); while (connections.length >= max) { const { index, response } = await Promise.race( connections.map((req, index) => ({ index, response: getFile(req.url) })) ); files[index] = response; connections[index] = undefined; } } await Promise.all( connections .filter((i) => i !== undefined) .map((req) => getFile(req.url)) ).then((responses) => { responses.forEach((response, index) => { const { index: i } = connections[index]; files[i] = response; }); }); resolve(files); })(); }); };

添加注解 var download = async blob fileName = let link = windowURLcreateObjectURLblob; const a = documentcreateElementa; adownload = $fileName; ahref = link; documentbodyappendChilda; a

原文地址: https://www.cveoy.top/t/topic/bGNI 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录