JS大文件分片上传详解

#在Web开发中,大文件上传一直是一个挑战。传统的文件上传方法可能导致浏览器崩溃、服务器过载或上传超时。为了解决这个问题,我们可以使用文件分片(Chunking)技术,将大文件分割成多个小块(chunks),然后逐个上传这些小块。这样不仅可以提高上传的稳定性,还可以实现断点续传和并行上传。#

分片上传流程
  1. 前端准备:使用JavaScript的File API和Blob.prototype.slice()方法将文件分割成多个分片。
  2. 上传分片:通过Ajax(或Fetch API)等技术逐个上传分片到服务器。
  3. 服务端处理:服务器接收分片数据,并保存到临时位置。
  4. 合并分片:当所有分片上传完成后,服务器将所有分片合并成一个完整的文件。
  5. 验证与清理:验证合并后的文件完整性,并清理临时分片文件。
示例代码

前端代码(使用XMLHttpRequest和FormData进行分片上传):

function uploadFile(file, chunkSize = 1024 * 1024 * 5) { // 5MB per chunk  
    const totalChunks = Math.ceil(file.size / chunkSize);  
    let currentChunk = 0;  
  
    function uploadChunk(chunkStart, chunkEnd) {  
        const chunk = file.slice(chunkStart, chunkEnd);  
        const formData = new FormData();  
        formData.append('file', chunk);  
        formData.append('chunkNumber', currentChunk);  
        formData.append('chunkSize', chunkSize);  
        formData.append('totalChunks', totalChunks);  
        formData.append('fileName', file.name);  
  
        const xhr = new XMLHttpRequest();  
        xhr.open('POST', '/upload', true);  
        xhr.upload.onprogress = function(e) {  
            if (e.lengthComputable) {  
                console.log(`Chunk ${currentChunk + 1} uploaded: ${(e.loaded / e.total * 100).toFixed(2)}%`);  
            }  
        };  
        xhr.onload = function() {  
            if (xhr.status === 200) {  
                currentChunk++;  
                if (currentChunk < totalChunks) {  
                    uploadChunk(chunkEnd, chunkStart + chunkSize * (currentChunk + 1));  
                } else {  
                    console.log('All chunks uploaded successfully!');  
                }  
            } else {  
                console.error('Chunk upload failed:', xhr.statusText);  
            }  
        };  
        xhr.send(formData);  
    }  
  
    uploadChunk(0, chunkSize);  
}  
  
// 使用方法:  
const fileInput = document.querySelector('input[type="file"]');  
fileInput.addEventListener('change', function(e) {  
    const file = e.target.files[0];  
    if (file) {  
        uploadFile(file);  
    }  
});

 后端代码(这里以Node.js和Express为例,实际中可能需要结合数据库和其他技术来追踪上传状态和合并文件):

const express = require('express');  
const fs = require('fs');  
const path = require('path');  
const app = express();  
const uploadDir = './uploads'; // 临时存储分片的目录  
  
app.post('/upload', (req, res) => {  
    const file = req.files.file; // 假设你使用了中间件来处理multipart/form-data请求  
    const chunkNumber = parseInt(req.body.chunkNumber, 10);  
    const chunkSize = parseInt(req.body.chunkSize, 10);  
    const totalChunks = parseInt(req.body.totalChunks, 10);  
    const fileName = req.body.fileName;  
  
    // 创建文件路径  
    const filePath = path.join(uploadDir, `${fileName}_${chunkNumber}`);  
  
    // 保存文件到临时位置  
    file.mv(filePath, (err) => {  
        if (err) {  
            return res.status(500).send(err);  
        }  
  
        // 这里可以添加代码来检查所有分片是否上传完成,并合并它们  
  
        res.send('Chunk uploaded successfully!');  
    });  
});  
  
// ... 其他路由和中间件配置 ...  
  
app.listen(3000, () => {  
    console.log('Server listening on port 3000');  
});

 注意:上述示例仅用于演示目的,并未包含完整的错误处理和文件合并逻辑。在实际应用中,你需要添加更多的逻辑来实现

 

  • 13
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值