大文件上传通常需要分片处理、断点续传等技术来提高上传效率和可靠性。以下是一个简单的JavaScript示例,展示如何实现大文件的分片上传和断点续传:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>大文件上传</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/axios/0.24.0/axios.min.js"></script>
</head>
<body>
    <input type="file" id="fileInput" />
    <button id="uploadBtn">上传</button>
    <progress id="progressBar" value="0" max="100"></progress>

    <script>
        // 请求基准地址
        axios.defaults.baseURL = 'http://localhost:3000';

        // 选中的文件
        var file = null;

        // 选择文件
        document.getElementById('fileInput').onchange = function(event) {
            file = event.target.files[0];
        };

        // 开始上传
        document.getElementById('uploadBtn').onclick = async function() {
            if (!file) return;

            const chunkSize = 10 * 1024 * 1024; // 10MB 切片大小
            const chunks = fileToChunks(file, chunkSize);
            const chunkHashes = await getChunksHashes(chunks);
            const uploadedChunks = new Set(JSON.parse(localStorage.getItem(file.name)) || []);

            for (let i = 0; i < chunks.length; i++) {
                if (uploadedChunks.has(i)) {
                    console.log(`Chunk ${i} 已经上传`);
                    continue;
                }

                const formData = new FormData();
                formData.append('chunk', chunks[i]);
                formData.append('hash', chunkHashes[i]);
                formData.append('index', i);
                formData.append('filename', file.name);

                try {
                    const response = await axios.post('/upload', formData);
                    console.log(`Chunk ${i} 上传成功`);
                    uploadedChunks.add(i);
                } catch (error) {
                    console.error(`Chunk ${i} 上传失败`, error);
                }
            }

            await axios.get('/merge', { params: { filename: file.name } });
            console.log('上传完成');
        };

        function fileToChunks(file, size) {
            const chunks = [];
            for (let start = 0; start < file.size; start += size) {
                const chunk = file.slice(start, start + size);
                chunks.push({ hash: Date.now(), chunk: chunk });
            }
            return chunks;
        }

        async function getChunksHashes(chunks) {
            const hashes = [];
            for (const chunk of chunks) {
                const hash = await new Promise((resolve) => {
                    const reader = new FileReader();
                    reader.onload = (event) => {
                        resolve(spark.end(event.target.result));
                    };
                    reader.readAsArrayBuffer(chunk.chunk);
                });
                hashes.push(hash);
            }
            return hashes;
        }
    </script>
</body>
</html>

代码解析:

  1. 文件选择与切片

    • 用户选择文件后,代码将文件分片,每个分片大小为10MB。
    • fileToChunks函数负责将文件分割成多个分片,并为每个分片生成一个唯一的哈希值。
  2. 上传分片

    • 使用axios库将每个分片上传到服务器。
    • 每个分片上传成功后,将分片索引记录到localStorage中,以便断点续传。
  3. 合并分片

    • 所有分片上传完成后,通过GET请求通知服务器合并分片。
  4. 进度展示

    • 使用<progress>元素实时展示上传进度。

进阶功能:

  • 断点续传:通过localStorage记录已上传的分片索引,下次上传时跳过已上传的部分。
  • 并发控制:可以进一步优化,限制同时上传的分片数量,避免浏览器内存溢出。

阿芯爱编程
0 声望1 粉丝

php ,java,nodejs