// 文件输入元素
const fileInput = document.getElementById('file-input');
fileInput.addEventListener('change', handleFileSelect, false);
// 文件选择事件处理器
async function handleFileSelect(event) {
const file = event.target.files[0];
if (file) {
const chunkSize = 1 * 1024 * 1024; // 1MB
const chunks = createChunks(file, chunkSize);
if (chunks.length >= 3) {
await uploadChunksWithQueue(chunks, 3); // 同时最多上传3个分片
} else {
await uploadChunksConcurrently(chunks); // 上传文件不大,直接全部上传
}
console.log('All chunks have been uploaded.');
}
}
// 创建分片数组
function createChunks(file, chunkSize) {
const chunks = []; // 初始化一个空数组,用于存储所有分片信息
for (let i = 0; i < file.size; i += chunkSize) { // 遍历文件,每次增加chunkSize字节
const chunk = file.slice(i, Math.min(file.size, i + chunkSize)); // 使用slice方法获取文件的一个分片
chunks.push({ // 将分片信息作为一个对象推入chunks数组
start: i, // 分片的起始位置
end: Math.min(file.size, i + chunkSize), // 分片的结束位置,确保不超过文件大小
data: chunk // 分片的数据,由slice方法返回的Blob或File对象
});
}
return chunks; // 返回包含所有分片信息的数组
}
// 并发上传分片
async function uploadChunksConcurrently(chunks) {
const promises = chunks.map(chunk => uploadChunk(chunk)); // 创建Promise数组
await Promise.all(promises); // 等待所有Promise完成
}
// 并发上传分片,使用队列限制并发数
async function uploadChunksWithQueue(chunks, maxConcurrent) {
const queue = []; // 初始化队列
let activeRequests = 0; // 当前活动的请求数量
// 将所有分片添加到队列中
chunks.forEach(chunk => queue.push(() => uploadChunk(chunk)));
while (queue.length > 0) { // 当队列不为空时循环
if (activeRequests < maxConcurrent) { // 如果当前活动请求小于最大并发数
activeRequests++;
const task = queue.shift(); // 从队列头部取出任务
try {
await task(); // 执行上传任务
} catch (error) {
console.error('Error uploading chunk:', error);
} finally {
activeRequests--; // 无论成功或失败,减少活动请求计数
}
}
await new Promise(resolve => setTimeout(resolve, 0)); // 让出执行权,防止死锁
}
}
// 上传单个分片
async function uploadChunk(chunk) {
try {
const formData = new FormData();
formData.append('chunk', chunk.data);
formData.append('chunkStart', chunk.start);
formData.append('chunkEnd', chunk.end);
const response = await fetch('/upload-chunk', {
method: 'POST',
body: formData
});
if (!response.ok) {
throw new Error(`Failed to upload chunk from ${chunk.start} to ${chunk.end}`);
}
} catch (error) {
console.error('Error uploading chunk:', error);
// 这里可以添加错误处理逻辑,比如重试
}
}
js分片上传
最新推荐文章于 2025-03-22 17:52:03 发布