概述通过 Range 请求按偏移拉取资源,保存进度以支持中断恢复,并对数据进行校验以保障可靠性。断点续传与校验async function sha256(bytes) {

const buf = await crypto.subtle.digest('SHA-256', bytes);

return Array.from(new Uint8Array(buf)).map(x => x.toString(16).padStart(2,'0')).join('');

}

async function downloadWithRange(url, chunkSize = 1024 * 1024) {

let offset = await loadProgress(url);

const parts = [];

while (true) {

const res = await fetch(url, { headers: { Range: `bytes=${offset}-${offset + chunkSize - 1}` } });

if (res.status === 416) break;

if (!res.ok && res.status !== 206) throw new Error('range fetch failed');

const ab = await res.arrayBuffer();

const bytes = new Uint8Array(ab);

parts.push(bytes);

offset += bytes.length;

await saveProgress(url, offset);

if (bytes.length < chunkSize) break;

}

const total = parts.reduce((n, p) => n + p.length, 0);

const out = new Uint8Array(total);

let i = 0;

for (const p of parts) { out.set(p, i); i += p.length; }

const digest = await sha256(out);

return { bytes: out, digest };

}

进度持久化示例function openDB(name) {

return new Promise((resolve, reject) => {

const r = indexedDB.open(name, 1);

r.onupgradeneeded = () => { const db = r.result; if (!db.objectStoreNames.contains('progress')) db.createObjectStore('progress'); };

r.onsuccess = () => resolve(r.result);

r.onerror = () => reject(r.error);

});

}

async function saveProgress(key, value) {

const db = await openDB('range');

const tx = db.transaction('progress', 'readwrite');

tx.objectStore('progress').put(value, key);

await new Promise((resolve, reject) => { tx.oncomplete = resolve; tx.onerror = () => reject(tx.error); });

db.close();

}

async function loadProgress(key) {

const db = await openDB('range');

const tx = db.transaction('progress', 'readonly');

const req = tx.objectStore('progress').get(key);

const val = await new Promise((resolve, reject) => { req.onsuccess = () => resolve(req.result || 0); req.onerror = () => reject(req.error); });

db.close();

return val;

}

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部