文件上传之大文件分块上传进度控制处理

在分块上传内容结束以后的事件监听,我们会实现 unlinkSync 删除临时文件操作,那么试想一下,在这个事件监听中,我们是否可以通过totalChunks以及currentChunk获取当前上传的进度情况呢?

后端

upload上传接口:
app.post('/upload',upload.single('file'),(req,res) => {
    const file = req.file; 
    const filename = req.body.filename;
    const totalChunks = parseInt(req.body.totalChunks);    // 获取总块数
    const currentChunk = parseInt(req.body.currentChunk);  // 获取当前块数
    const chunkPath = path.join(
        "uploads/",
        `${filename}-chunk-${currentChunk}`
    ); 
 
    const chunkStream = fs.createReadStream(file.path);
    const writeStream = fs.createWriteStream(chunkPath);
 
    chunkStream.pipe(writeStream);
 
    // 对分块上传内容结束以后的事件监听
    chunkStream.on("end", () => {
        fs.unlinkSync(file.path); //读取文件块的流结束后,删除临时文件

        // 打印 progress 我们就可以获取到文件进度情况
        const progress = ((currentChunk + 1) / totalChunks) * 100;  // 计算上传进度情况
        res.json({ progress }); // 服务器端向客户端进行返回操作
    });
});

前端

html:

<input type="file" id="fileInput">
<progress value="0" max="100" id="progress"></progress>  //设置一个进度条
<button onclick="upload()">上传文件</button>
script:
async function upload() {
    const fileInput = document.getElementById('fileInput'); //获取input框
    const file = fileInput.files[0]; // 对input的文件进行获取
 
    const chunkSize = 1*1024*1024;  //初始化分块的尺寸 每块分块文件大小为1MB(1兆)
    const totalChunks = Math.ceil(file.size / chunkSize); //通过文件尺寸计算出所有的块数
    let currentChunk = 0; //设置块的初始值
 
    // 通过while循环处理
    while (currentChunk < totalChunks){
        const start = currentChunk * chunkSize;  // 计算当前块的起始位置
        const end = Math.min(start + chunkSize, file.size); // 计算当前块的结束  Math.min:返回一组数值中的最小值
        const chunk = file.slice(start, end); // 切割文件获取当前块
 
        const formData = new FormData();
        formData.append('file', chunk); // 添加当前块到 FormData 对象
        formData.append('filename', file.name); // 添加文件名到 FormData 对象
        formData.append('totalChunks', totalChunks); // 添加总块数到 FormData 对象
        formData.append('currentChunk', currentChunk); // 添加当前块数到 FormData 对象
    
        try{
            // 获取返回的内容(进度)
            const res = await axios.post(
                'http://localhost:3000/upload',
                formData,
                {
                    headers:{
                        'Content-Type':'multipart/form-data',
                    },
                }
            ); //发送当前块的上传请求

            const { progress } = res.data;  // 获取当前块的上传进度
            document.getElementById('progress').value = progress; // 更新进度
    
        }catch(error){
            console.error(error);
            return;
        }
 
        currentChunk++; //增加当前块数,继续下一块的上传(实现循环操作)
    }
 
    // 当所有分块文件发送完毕,发起合并请求操作
    try{
        const postData = { filename:file.name,totalChunks:totalChunks }; //构造合并请求的数据
        await http.post('http://localhost:3000/merge', postData,{
            headers: {
            'Content-Type': 'application/json'
            }
        }); //发送合并请求
    }catch(error){
        console.error(error);
    }
}

再次发送文件,进度条已经正常显示:

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值