前端分片上传大文件(支持1G以上的超大文件)

在Web开发中,文件上传是一个常见的需求。尤其是当我们需要上传大文件(如视频、图片、文档等)时,如何高效地上传这些文件是一个重要的课题。传统的文件上传方式可能会受到文件大小的限制,因而出现了分片上传的方案。本文将介绍如何在前端实现一个支持1G以上大文件的分片上传功能。

分片上传的基本原理

分片上传的核心思想是将大文件切割成多个小块(片),然后逐个将这些小块上传到服务器。这样可以避免因网络不稳定导致上传失败的情况,也可以对上传的进度进行监控。上传完成后,服务器再将这些小块合并成完整的文件。

分片上传的步骤

  1. 文件选择:用户选择要上传的文件。
  2. 切分文件:将大文件切分为多个小块。
  3. 逐块上传:依次上传每个小块,并在上传过程中监控上传进度。
  4. 合并文件:在服务器端接收所有小块后,将它们合并为完整的文件。

代码示例

以下是一个使用JavaScript实现前端分片上传大文件的示例:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>分片上传示例</title>
</head>
<body>
    <input type="file" id="fileInput" />
    <button id="uploadBtn">上传文件</button>
    <progress id="progressBar" value="0" max="100"></progress>
    <script>
        const CHUNK_SIZE = 1024 * 1024; // 1MB每片
        const fileInput = document.getElementById('fileInput');
        const uploadBtn = document.getElementById('uploadBtn');
        const progressBar = document.getElementById('progressBar');

        uploadBtn.onclick = async () => {
            const file = fileInput.files[0];
            if (!file) {
                alert("请先选择文件");
                return;
            }

            const totalChunks = Math.ceil(file.size / CHUNK_SIZE);
            let uploadedChunks = 0;

            for (let start = 0; start < file.size; start += CHUNK_SIZE) {
                const chunk = file.slice(start, start + CHUNK_SIZE);
                const success = await uploadChunk(chunk, uploadedChunks, totalChunks);
                if (success) {
                    uploadedChunks++;
                    progressBar.value = (uploadedChunks / totalChunks) * 100; // 更新进度条
                } else {
                    alert("上传失败");
                    return;
                }
            }
            alert("文件上传完成");
        };

        async function uploadChunk(chunk, chunkIndex, totalChunks) {
            const formData = new FormData();
            formData.append('file', chunk);
            formData.append('chunkIndex', chunkIndex);
            formData.append('totalChunks', totalChunks);

            // 发送请求到服务器
            try {
                const response = await fetch('/upload', {
                    method: 'POST',
                    body: formData
                });
                return response.ok; // 返回请求状态
            } catch (error) {
                console.error('上传出错:', error);
                return false; // 返回失败
            }
        }
    </script>
</body>
</html>

服务器端处理

虽然上述代码展示了客户端的实现部分,服务器端同样需要处理上传的分片。服务器接收到每片后,可以将其保存到临时位置,并记录当前上传的分片信息。最终当所有分片都上传完成后,可以将这些分片合并为一个完整的文件。

以下是一个简化的Node.js服务器端处理示例:

const express = require('express');
const multer = require('multer');
const fs = require('fs');
const path = require('path');

const app = express();
const upload = multer({ dest: 'uploads/' }); // 文件上传的临时目录

app.post('/upload', upload.single('file'), (req, res) => {
    const { chunkIndex, totalChunks } = req.body;
    const tempFilePath = path.join(__dirname, 'uploads', req.file.filename);

    fs.rename(tempFilePath, path.join(__dirname, 'uploads', `${req.file.filename}-${chunkIndex}`), (err) => {
        if (err) {
            return res.status(500).send('上传文件出错');
        }

        if (parseInt(chunkIndex) === parseInt(totalChunks) - 1) {
            // 合并文件的逻辑
            mergeChunks(req.file.filename, totalChunks);
        }

        res.send('分片上传成功');
    });
});

function mergeChunks(filename, totalChunks) {
    const writeStream = fs.createWriteStream(path.join(__dirname, 'uploads', filename));

    for (let i = 0; i < totalChunks; i++) {
        const chunkPath = path.join(__dirname, 'uploads', `${filename}-${i}`);
        const chunk = fs.readFileSync(chunkPath);
        writeStream.write(chunk);
        fs.unlinkSync(chunkPath); // 删除临时分片
    }

    writeStream.end();
}

app.listen(3000, () => {
    console.log('服务器已启动,监听3000端口');
});

总结

通过以上步骤,我们实现了一个上传超大文件的前端分片上传功能。用户选择文件后,文件被切割成多个小块,并依次上传到服务器。上传完成后,后台将分片合并为原始文件。这种方式不仅提升了上传体验,还能有效应对大文件上传的困难。

希望本文能为你提供一些帮助,如果有任何问题,欢迎随时交流!

点赞(0) 打赏

微信小程序

微信扫一扫体验

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部