概述大文件上传需要分块、校验与状态持久化。本文展示使用 Web Streams、分块与 IndexedDB 的端到端实现框架。环境检测const supportsStreams = typeof ReadableStream === 'function'; 分块与上传async function* chunkFile(file, size) { let offset = 0; while (offset < file.size) { const blob = file.slice(offset, offset + size); const buf = await blob.arrayBuffer(); yield new Uint8Array(buf); offset += size; } } async function uploadChunks(file, endpoint, size = 1024 * 1024) { let index = await loadProgress(file.name); for await (const chunk of chunkFile(file, size)) { if (index && index.sent >= index.total) break; const res = await fetch(endpoint, { method: 'POST', headers: { 'X-Chunk-Index': String(index ? index.sent : 0), 'X-File-Name': file.name }, body: chunk }); if (!res.ok) throw new Error('upload failed'); await saveProgress(file.name, { sent: (index ? index.sent : 0) + 1, total: Math.ceil(file.size / size) }); index = await loadProgress(file.name); } } IndexedDB 持久化上传状态function openDB(name) { return new Promise((resolve, reject) => { const req = indexedDB.open(name, 1); req.onupgradeneeded = () => { const db = req.result; if (!db.objectStoreNames.contains('upload')) { db.createObjectStore('upload', { keyPath: 'fileName' }); } }; req.onsuccess = () => resolve(req.result); req.onerror = () => reject(req.error); }); } async function saveProgress(fileName, state) { const db = await openDB('uploaddb'); const tx = db.transaction('upload', 'readwrite'); tx.objectStore('upload').put({ fileName, ...state }); await new Promise((resolve, reject) => { tx.oncomplete = resolve; tx.onerror = () => reject(tx.error); }); db.close(); } async function loadProgress(fileName) { const db = await openDB('uploaddb'); const tx = db.transaction('upload', 'readonly'); const req = tx.objectStore('upload').get(fileName); const res = await new Promise((resolve, reject) => { req.onsuccess = () => resolve(req.result); req.onerror = () => reject(req.error); }); db.close(); return res || { sent: 0, total: 0 }; } 断点续传与恢复保存分块总数与已上传索引,页面刷新后继续。结合校验摘要确保服务端归并正确,可使用每块的散列头部字段。在失败时重试,并在离线状态下暂停并提示用户。

发表评论 取消回复