js分片上传

// 文件输入元素
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);
        // 这里可以添加错误处理逻辑,比如重试
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值